Let's say you operate an online business selling shoes. You want to provide personalization for your logged in customers by storing their preferred shoe size. By storing their shoe size as a part of their customer data, you can auto-select their shoe size when navigating to a product detail page, or provide search results with only shoes in their size.
Customization in commercetools Composable Commerce
resourceTypeId and a FieldDefinition. The FieldDefinition describes the new Custom Field, and the resourceTypeId indicates which resources are customizable using the Type.Create a Type
preferredShoeSize field to the Customer object, we need to create a new Type which contains the preferredShoeSize CustomField.POST request to the /<project-id>/types endpoint with the following payload:{
  "key": "customer-preferredShoeSize",
  "name": { "en": "Additional field to store preferred shoe size" },
  "resourceTypeIds": ["customer"],
  "fieldDefinitions": [
    {
      "type":{
        "name":"LocalizedString"
      },
      "name":"preferredShoeSize",
      "label":{
        "en":"Preferred Shoe Size"
      },
      "required":false,
      "inputHint":"SingleLine"
    }
  ]
}
resourceTypeIds in this request indicate which resources we can use the Custom Field with. We also specify that we want to use a LocalizedString type.preferredShoeSize field:{
  "id": "b9c5e724-8d86-485b-ae1e-a1d3bcc8deae",
  "version": 1,
  "key": "customer-preferredShoeSize",
  "name": {
    "en": "Additional field to store preferred shoe size"
  },
  "resourceTypeIds": [
    "customer"
  ],
  "fieldDefinitions": [
    {
      "name": "preferredShoeSize",
      "label": {
        "en": "Preferred Shoe Size"
      },
      "required": false,
      "type": {
        "name": "LocalizedString"
      },
      "inputHint": "SingleLine"
    }
  ],
  "createdAt": "2015-10-02T09:44:24.628Z",
  "lastModifiedAt": "2015-10-02T09:44:24.628Z"
}Create a Customer with the preferredShoeSize CustomField
POST request to the /<project-id>/customers API endpoint with following payload:{
  "customerNumber":"Registered-0042",
  "email":"john.doe@example.com",
  "firstName": "John",
  "lastName": "Doe",
  "password": "secret123",
  "custom": {
    "type": {
      "key": "customer-preferredShoeSize",
      "typeId": "type"
    },
    "fields": {
      "preferredShoeSize": {
        "en":"38"
      }
    }
  }
}
You should receive a response to that request with the code 201 containing the customized customer resource:
{
    "customer": {
        "id": "85c8d7a1-da11-477f-8ad7-a19c6c274f71",
        "version": 1,
        "createdAt": "2018-12-14T14:06:05.555Z",
        "lastModifiedAt": "2018-12-14T14:06:05.555Z",
        "customerNumber": "Registered-0042",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "password": "aVlInP9GSgTfLob/D619djMauHcxyXvhhYKZUtTjm3s=$3S3KeoGMjHXiHpVr90QoSydU3O1u2qcXcrvsu9dWHao=",
        "addresses": [],
        "shippingAddressIds": [],
        "billingAddressIds": [],
        "isEmailVerified": false,
        "custom": {
            "type": {
                "typeId": "type",
                "id": "b9c5e724-8d86-485b-ae1e-a1d3bcc8deae"
            },
            "fields": {
                "preferredShoeSize": {
                    "en": "38"
                }
            }
        }
    }
}
Update an existing Customer with a CustomField
Yes, we can. The API provides update actions for that.
customer-preferredShoeSize customer type instead of the default. To use the Custom Field on an existing customer, we need to have them use the custom-preferredShoeSize type so we can use the preferredShoeSize field.customer-preferredShoeSize customer type by sending the payload below with the update request to the Customer API endpoint:/{project-id}/customers/{id-of-customer-jane-roe} with following payload:{
  "version":1,
  "actions": [{
    "action": "setCustomType",
    "type": {
      "id": "b9c5e724-8d86-485b-ae1e-a1d3bcc8deae",
      "typeId": "type"
    }
  }]
}
customer-preferredShoeSize number by Querying the CustomTypes API endpoint if needed.The response to the update action shows that the customer now contains the Type:
{
  "id": "85c8d7a1-da11-477f-8ad7-a19c6c274f71",
  "version": 2,
  "createdAt": "2018-12-14T14:06:05.555Z",
  "lastModifiedAt": "2018-12-14T14:25:57.885Z",
  "customerNumber": "Registered-0024",
  "email": "jane.roe@example.com",
  "firstName": "Jane",
  "lastName": "Roe",
  "password": "aVlInP9GSgTfLob/D619djMauHcxyXvhhYKZUtTjm3s=$3S3KeoGMjHXiHpVr90QoSydU3O1u2qcXcrvsu9dWHao=",
  "addresses": [],
  "shippingAddressIds": [],
  "billingAddressIds": [],
  "isEmailVerified": false,
  "custom": {
    "type": {
      "typeId": "type",
      "id": "b9c5e724-8d86-485b-ae1e-a1d3bcc8deae"
    },
    "fields": {}
  }
}
As you can see the Type has been set, but there are no values for the fields:
  fields:{}
/{project-id}/customers/{id-of-customer-jane-roe} with following payload:{
  "version":2,
  "actions":[
    {
      "action":"setCustomField",
      "name": "preferredShoeSize",
      "value":{
        "en":"38"
      }
    }
  ]
}
preferredShoeSize field with the appropriate value:fields:{
  "preferredShoeSize": {
    "en":"38"
  }
}
Query Customer with CustomField
preferredShoeSize for queries on customers.preferredShoeSize of 38 and target them with a discount code.
We'll filter by this value for the English language part of the Localized String in preferredShoeSize by the predicate: preferredShoeSize(en="38").Since
preferredShoeSize is a CustomField we'll need to mark it like that, like so: custom(fields(preferredShoeSize(en="38")))The complete URL-encoded query request on the Customers endpoint is as follows:
GET {projectKey}/customers?where=custom(fields(preferredShoeSize(en%3D%2238%22)))
CustomerPagedQueryResponse customersWithShoeSize = apiRoot
  .customers()
  .get()
  .withWhere("custom(fields(preferredShoeSize(en=\"38\")))")
  .executeBlocking()
  .getBody();The response to the query should only contain customers with a preferred shoe size of 38 in your project.
Plenty of other use cases exist, for example:
- Storing loyalty points for each purchase by a customer.
- Adding contextual in-cart promotions by adding fields on cart LineItems.
And more!
Types and Custom Fields give you the flexibility to customize resources to the specific requirement of your business.