6 March 2024
Composable Commerce
HTTP API
New feature
Product catalogGraphQL

We introduced Product Tailoring in public beta, a new feature designed to enhance your product offerings across different markets. With Product Tailoring, you can customize product details like names, descriptions, slugs, and meta fields for specific brands or countries, using Stores to model these market segments.

By defining tailored product data, you can adapt product information to appeal to different markets and, in turn, increase visibility, customer loyalty, and order volumes.

Changes:

  • [API] Added Product Tailoring API.
  • [API] Added Product Tailoring Messages.
  • [GraphQL API] Added following types to the GraphQL schema: ProductTailoringDraft, ProductTailoring, ProductTailoringCreated, ProductTailoringData, ProductTailoringDeleted, ProductTailoringDescriptionSet, ProductTailoringNameSet, ProductTailoringPublished, ProductTailoringQueryResult, ProductTailoringSlugSet, ProductTailoringUnpublished, ProductTailoringUpdateAction, PublishTailoring, SetProductTailoringDescription, SetProductTailoringMetaAttributes, SetProductTailoringMetaDescription, SetProductTailoringMetaKeywords, SetProductTailoringMetaTitle, SetProductTailoringName, SetProductTailoringSlug, UnpublishTailoring.
  • [GraphQL API] Added fields productTailoring and productTailoringList to the InStore type.
  • [GraphQL API] Added fields productTailoring and productTailoringList to the Query type.
  • [GraphQL API] Added fields createProductTailoring, updateProductTailoring, and deleteProductTailoring to the Mutation type.

The following changes were introduced in terms of GraphQL SDL:

extend type InStore {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  productTailoring(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String,

    "Queries with specified Product ID"
    productId: String,

    "Queries with specified Product key"
    productKey: String): ProductTailoring

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  productTailoringList(where: String, sort: [String!], limit: Int, offset: Int): ProductTailoringQueryResult!
}

extend type Query {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  productTailoring(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String,

    "Queries with specified Product ID"
    productId: String,

    "Queries with specified Product key"
    productKey: String,

    "The mutation is only performed if the resource is part of the store. Can be used with store-specific OAuth permissions."
    storeKey: KeyReferenceInput): ProductTailoring

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  productTailoringList(where: String, sort: [String!], limit: Int, offset: Int): ProductTailoringQueryResult!
}

extend type Mutation {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  createProductTailoring(
    "The mutation is only performed if the resource is part of the store. Can be used with store-specific OAuth permissions."
    storeKey: KeyReferenceInput, draft: ProductTailoringDraft!): ProductTailoring

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  deleteProductTailoring(
    "The mutation is only performed if the resource is part of the store. Can be used with store-specific OAuth permissions."
    storeKey: KeyReferenceInput,

    "Queries with specified Product ID"
    productId: String,

    "Queries with specified Product key"
    productKey: String,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String, version: Long!): ProductTailoring

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  updateProductTailoring(
    "The mutation is only performed if the resource is part of the store. Can be used with store-specific OAuth permissions."
    storeKey: KeyReferenceInput,

    "Queries with specified Product ID"
    productId: String,

    "Queries with specified Product key"
    productKey: String,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String, actions: [ProductTailoringUpdateAction!]!, version: Long!): ProductTailoring
}

"BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
input ProductTailoringDraft {
  product: ResourceIdentifierInput!
  name: [LocalizedStringItemInputType!]
  key: String
  description: [LocalizedStringItemInputType!]
  slug: [LocalizedStringItemInputType!]
  metaTitle: [LocalizedStringItemInputType!]
  metaDescription: [LocalizedStringItemInputType!]
  metaKeywords: [LocalizedStringItemInputType!]
  publish: Boolean
}

"BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
type ProductTailoring implements Versioned {
  key: String
  productRef: Reference!
  product: Product
  storeRef: KeyReference!
  store: Store
  current: ProductTailoringData
  staged: ProductTailoringData
  published: Boolean!
  hasStagedChanges: Boolean!
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}

type ProductTailoringCreated implements MessagePayload {
  publish: Boolean!
  storeRef: KeyReference!
  productRef: Reference!
  key: String
  productKey: String
  name(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  description(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  slug(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  nameAllLocales: [LocalizedString!]
  slugAllLocales: [LocalizedString!]
  descriptionAllLocales: [LocalizedString!]
  type: String!
}

"BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
type ProductTailoringData {
  name(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  nameAllLocales: [LocalizedString!]
  description(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  descriptionAllLocales: [LocalizedString!]
  slug(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  slugAllLocales: [LocalizedString!]
  metaTitle(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaTitleAllLocales: [LocalizedString!]
  metaDescription(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaDescriptionAllLocales: [LocalizedString!]
  metaKeywords(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaKeywordsAllLocales: [LocalizedString!]
}

type ProductTailoringDeleted implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  type: String!
}

type ProductTailoringDescriptionSet implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  description(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  oldDescription(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  descriptionAllLocales: [LocalizedString!]
  oldDescriptionAllLocales: [LocalizedString!]
  type: String!
}

type ProductTailoringNameSet implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  name(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  oldName(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  nameAllLocales: [LocalizedString!]
  oldNameAllLocales: [LocalizedString!]
  type: String!
}

type ProductTailoringPublished implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  type: String!
}

type ProductTailoringQueryResult {
  offset: Int!
  count: Int!
  total: Long!
  exists: Boolean!
  results: [ProductTailoring!]!
}

type ProductTailoringSlugSet implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  slug(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  oldSlug(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  slugAllLocales: [LocalizedString!]
  oldSlugAllLocales: [LocalizedString!]
  type: String!
}

type ProductTailoringUnpublished implements MessagePayload {
  storeRef: KeyReference!
  productRef: Reference!
  productKey: String
  type: String!
}

"BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
input ProductTailoringUpdateAction {
  publish: PublishTailoring
  unpublish: UnpublishTailoring
  setDescription: SetProductTailoringDescription
  setMetaAttributes: SetProductTailoringMetaAttributes
  setMetaDescription: SetProductTailoringMetaDescription
  setMetaKeywords: SetProductTailoringMetaKeywords
  setMetaTitle: SetProductTailoringMetaTitle
  setName: SetProductTailoringName
  setSlug: SetProductTailoringSlug
}

input PublishTailoring {
  dummy: String
}

input SetProductTailoringDescription {
  description: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringMetaAttributes {
  metaDescription: [LocalizedStringItemInputType!]
  metaKeywords: [LocalizedStringItemInputType!]
  metaTitle: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringMetaDescription {
  metaDescription: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringMetaKeywords {
  metaKeywords: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringMetaTitle {
  metaTitle: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringName {
  name: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input SetProductTailoringSlug {
  slug: [LocalizedStringItemInputType!]
  staged: Boolean = true
}

input UnpublishTailoring {
  dummy: String
}