Create custom properties for accounts

This section describes how to use the Commerce REST web services APIs to add custom properties to accounts.

See Use the REST APIs for information you need to know before using the services.

Note that you can also create custom properties for the contacts associated with accounts. Contacts are stored as shopper profiles, so any custom properties you add to shopper profiles are available for contacts as well. See Manage Shopper Profiles for information.

View an account

To view an existing account, first log into the Admin API on the administration server using a profile that has the Administrator role. For example:

POST /ccadmin/v1/mfalogin HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=admin1@example.com&password=A3ddj3w2&totp_code=365214

Then issue a request to the getOrganization endpoint, providing the ID of the account you want to view, and including the access token that was returned by /ccadmin/v1/mfalogin. For example:

GET /ccadmin/v1/organizations/100002 HTTP/1.1
Authorization: Bearer <access_token>

The response shows the predefined account properties that are exposed by Commerce, and the values of the properties in the specified account. Note that the members property is an array in which the elements are the IDs of the contacts for the account:

{
    "customerType": "Supplier",
    "contract": {
        "creationDate": "2016-10-17T20:25:44.000Z",
        "startDate": null,
        "externalContractReference": "",
        "description": null,
        "catalog": {
            "repositoryId": "cloudCatalog"
        },
        "terms": null,
        "priceListGroup": {
            "repositoryId": "defaultPriceGroup"
        },
        "endDate": null,
        "displayName": "Sherman",
        "repositoryId": "100002"
    },
    "vatReferenceNumber": null,
    "links": [
        {
            "rel": "self",
            "href": "http://myserver.example.com:7002/ccadmin/v1/organizations/100002"
        }
    ],
    "organizationLogoURL": null,
    "type": "company",
    "repositoryId": "100002",
    "dunsNumber": 000000000,
    "uniqueId": null,
    "id": "100002",
    "description": "Supplier of sprockets to a wide range of industries.",
    "name": "Sherman Sprockets",
    "active": true,
    "secondaryAddresses": [
        {
            "address": {
                "postalCode": "02116",
                "phoneNumber": "1-555-555-1212",
                "state": "MA",
                "address1": "1 Wixom Street",
                "address2": null,
                "companyName": "Sherman Sprockets",
                "repositoryId": "120002",
                "country": "US",
                "city": "Boston"
            },
            "addressType": "Sherman"
        }
    ],
    "billingAddress": null,
    "taxReferenceNumber": null,
    "shippingAddress": {
        "postalCode": "02116",
        "phoneNumber": "1-555-555-1212",
        "state": "MA",
        "address1": "1 Wixom Street",
        "address2": null,
        "companyName": "Sherman Sprockets",
        "repositoryId": "120002",
        "country": "US",
        "city": "Boston"
    },
    "members": [
        {
            "repositoryId": "110001"
        }
        {
            "repositoryId": "110002"
        }
    ],
    "organizationLogo": null
}

You can modify the values of the properties of an account using the PUT /ccadmin/v1/organizations/{id} endpoint on the administration server.

View the organization item type

Accounts include a predefined set of properties for storing information, such as the DUNS number and the account name. The set of properties available for an account is determined by the organization item type, which serves as a template for accounts. You can view this item type with the following call:

GET /ccadmin/v1/itemTypes/organization HTTP/1.1
Authorization: Bearer <access_token>

The following example shows a portion of the response corresponding to one of the predefined account properties. Each property has a group of attributes whose values control the behavior associated with the property:

{
    "id": "organization",
    "links": [
        {
            "rel": "self",
            "href": "http://myserver.example.com:7002/ccadmin/v1/itemTypes/organization"
        }
    ],
    "displayName": "Organization",
    "specifications": [
        {
         ...
            "writable": true,
            "localizable": false,
            "label": "Description",
            "type": "shortText",
            "id": "description",
            "uiEditorType": "shortText",
            "textSearchable": false,
            "multiSelect": null,
            "dimension": false,
            "internalOnly": false,
            "default": null,
            "editableAttributes": [
                "textSearchable",
                "multiSelect",
                "dimension",
                "internalOnly",
                "default",
                "label",
                "required",
                "searchable"
            ],
            "length": 254,
            "required": false,
            "searchable": false
        },
        ...
}

To modify the organization item type, you can create custom properties or modify existing properties by setting the values of these attributes. See Settable attributes of shopper type properties for descriptions of these attributes.

Add custom properties to the organization item type

You can use the updateItemType endpoint in the Commerce Admin API to add custom properties to the organization item type. When you add a custom property to the organization item type, the property is added to all accounts, including any new accounts created afterward and any accounts that already exist.

The ID of a custom property must include the underscore character (_). This ensures that the ID will not conflict with any properties that Commerce adds to accounts in the future. The endpoint produces an error if you attempt to create a custom property without an underscore in its ID.

The following example illustrates using the updateItemType endpoint to add a custom property. Note that the request header must specify the x-ccasset-language value:

PUT /ccadmin/v1/itemTypes/organization HTTP/1.1
Authorization: Bearer <access_token>
x-ccasset-language: en

{
  "id": "organization",
  "specifications": [
    {
         "id": "customer_tier",
         "label": "Customer tier",
         "type": "shortText",
         "uiEditorType": "shortText",
         "internalOnly": false,
         "required": false,
         "audienceVisibility": "b2b",
    }
  ]
}

The response includes the custom property you added:

...
{
     "writable": true,
     "localizable": false,
     "label": "Customer tier",
     "type": "shortText",
     "id": "customer_tier",
     "uiEditorType": "shortText",
     "textSearchable": false,
     "multiSelect": null,
     "dimension": false,
     "internalOnly": false,
     "default": null,
     "editableAttributes": [
         "textSearchable",
         "multiSelect",
         "dimension",
         "internalOnly",
         "default",
         "label",
         "required",
         "searchable"
         "audienceVisibility"
     ],
     "length": 254,
     "required": false,
     "searchable": false
 },
...

The audienceVisibility is the string that determines whether the property appears as a choice in the Attributes field of the audience interface. For account properties, this value should be set to b2b. See Define Audiences.

You can create a new account and set the values of custom properties (as well as the predefined properties) using the createOrganization endpoint. To set a custom property on an existing account, use the updateOrganization endpoint. For example:

PUT /ccadmin/v1/organizations/100001 HTTP/1.1
Authorization: Bearer <access_token>

{
     "customer_tier": "silver"
}

Add a custom property that lets administrators log internal notes

This section describes a code sample that adds a custom property to the organization type. This property displays a rich-text field on each account’s General tab in the Commerce administration interface. Account administrators can use this editor to log internal notes about the account. In this example, the rich-text field is used to add and track internal notes related to registration requests.

Note: Keep in mind that you cannot search on this custom property in the administration interface. You can search only on custom short text properties. See Work with accounts for information about searching on custom properties.

The following sample request creates the rich-text editor, which is added to all accounts, including any new accounts created afterward and any accounts that already exist.

PUT /ccadmin/v1/itemTypes/organization HTTP/1.1
Authorization: Bearer <access_token>
x-ccasset-language: en

{
  "specifications": [
    {
     "label": "Internal Notes for Registration Requests",
     "id": "internal_notes",
     "default": null,
     "required": false,
     "localizable": false,
     "internalOnly": false,
     "textSearchable": false,
     "searchable": false,
     "multiSelect": false,
     "type": "richText",
     "uiEditorType": "richText"
    }
  ]
}

The editor appears at the bottom of the General tab for each account, in the Additional Information section. As with all property editors, the editor appears in each account, but the values are unique to the account where they are entered.

Keep the following tips in mind when you use the editor to create internal notes:

  • Format each individual note, or task, as a separate bullet point.
  • Each internal user should add their name or username to each note they create.
  • Append new notes to the existing list. It is best not to modify or delete any existing notes because there is no way to restore a note that has been changed or deleted.

The following illustration shows an account’s rich-text editor, with notes from three different account administrators.

rich-text editor for an account

Render custom properties of accounts on the storefront

To render custom properties of accounts on your storefront, customize the JavaScript in the Account Details widget to access the dynamicProperties observable array in the Organization view model. For example:

define(
    //-------------------------------------------------------------------
    // DEPENDENCIES
    //-------------------------------------------------------------------
    ['jquery', 'knockout', 'ccLogger', 'ccRestClient', 'ccConstants',
    'viewModels/dynamicPropertyMetaContainer'],
    //-------------------------------------------------------------------
    // Module definition
    //-------------------------------------------------------------------
    function($, ko, CCLogger, ccRestClient, CCConstants,
      DynamicPropertyMetaContainer) {
      'use strict';
      return {
        dynamicProperties: ko.observableArray(),
        onLoad : function(widget) {
        },

        beforeAppear: function(page) {
         var widget = this;
         if (widget.user() && widget.user().organizations &&
            widget.user().organizations().length > 0) {
              this.getDynamicPropertyMetadata(widget);
            }
         },

        getDynamicPropertyMetadata: function(widget) {
           var dynamicPropertyMetaInfo =
              DynamicPropertyMetaContainer.getInstance();
           if (dynamicPropertyMetaInfo &&
              dynamicPropertyMetaInfo.dynamicPropertyMetaCache &&
              dynamicPropertyMetaInfo.dynamicPropertyMetaCache.
              hasOwnProperty("organization")) {
                this.dynamicProperties(dynamicPropertyMetaInfo.
                dynamicPropertyMetaCache["organization"]);
            }
          },

         updateDynamicProperties: function() {
           var data = ko.toJS(this.user().organizations()[0]);
              ccRestClient.request("updateOrganization",data,
              this.updateDynamicPropertySuccess.bind(this),
              this.updateDynamicPropertyFailure.bind(this),
              this.user().organizations()[0].id());
           },
           updateDynamicPropertySuccess: function() {
           },
           updateDynamicPropertyFailure: function() {
           }
       }
     }
);

Modify the widget’s template file to include Knockout bindings similar to the following:

<div id="CC-org-dynamic-property">
  <!-- ko foreach: dynamicProperties -->
    <label data-bind="attr: {id: 'CC-label-org-dynamicProperty-'+id()},
     text: label">
    </label>
    <input data-bind="attr: {id: 'CC-edit-org-dynamicProperty-'+id(),
     type: uiEditorType, required: required},
     value: $parent.user().organizations()[0][id()]">
    <br>
  <!--/ko-->
</div>