Create a custom shopper context widget

This section describes how to create a sample widget that lets a logged-in shopper select a different catalog and price groups set on a storefront.

The widget makes an endpoint call to get a set of custom order properties. The values of these properties will be used to display the UI for a context selector that a shopper uses to select a catalog and price list groups. The custom widget’s JavaScript file extends the storefront’s ContextViewModel class by implementing a callback function. When a shopper successfully switches context, this function invokes the External Price Group and Catalog webhook, which makes a call to the external system to obtain the catalog and price groups to use.

Create the custom order properties

A settable attribute of order type properties, externalShopperContext lets you specify if the properties and their values are sent as name/value pairs in the webhook request body. To add custom properties to an order type, issue a PUT request to the /ccadmin/v1/orderTypes/{id} endpoint on the administration server. (See Add custom properties to an order type for more information.)

The following example shows a sample request that adds the defaultPriceListGroup, defaultCatalog, defaultAdditionalPriceListGroups, responseCode, and message properties to the order type. Note that the externalShopperContext attribute is set to true for these properties.

{
   "properties":{
      "defaultPriceListGroup":{
         "dimension":true,
         "multiSelect":true,
         "textSearchable":false,
         "default":"",
         "internalOnly":false,
         "localizable":false,
         "label":"defaultPriceListGroup",
         "type":"shortText",
         "uiEditorType":"shortText",
         "required":false,
         "searchable":false,
         "audienceVisibility":false,
         "externalShopperContext":true
      },
      "defaultCatalog":{
         "dimension":true,
         "multiSelect":true,
         "textSearchable":false,
         "default":"",
         "internalOnly":false,
         "localizable":false,
         "label":"defaultCatalog",
         "type":"shortText",
         "uiEditorType":"shortText",
         "required":false,
         "searchable":false,
         "audienceVisibility":false,
         "externalShopperContext":true
      },
      "responseCode":{
         "dimension":true,
         "multiSelect":true,
         "textSearchable":false,
         "default":"",
         "internalOnly":false,
         "localizable":false,
         "label":"responseCode",
         "type":"shortText",
         "uiEditorType":"shortText",
         "required":false,
         "searchable":false,
         "audienceVisibility":false,
         "externalShopperContext":true
      },
      "message":{
         "dimension":true,
         "multiSelect":true,
         "textSearchable":false,
         "default":"",
         "internalOnly":false,
         "localizable":false,
         "label":"message",
         "type":"shortText",
         "uiEditorType":"shortText",
         "required":false,
         "searchable":false,
         "audienceVisibility":false,
         "externalShopperContext":true
      },
      "defaultAdditionalPriceListGroups":{
         "dimension":true,
         "multiSelect":true,
         "textSearchable":false,
         "default":"",
         "internalOnly":false,
         "localizable":false,
         "label":"defaultAdditionalPriceListGroups",
         "type":"shortText",
         "uiEditorType":"shortText",
         "required":false,
         "searchable":false,
         "audienceVisibility":false,
         "externalShopperContext":true
      }
   }
}

Create the shopper context widget extension

The ext.json file contains metadata for the extension. For example:

{
  "extensionID": "c2e6a60e-579a-4190-af3e-5edc0cd8a725",
  "developerID": "999999",
  "createdBy": "Demo Corp.",
  "name": "ShopperContextSelectorDemoWidget",
  "version": 1,
  "timeCreated": "2017-10-10",
  "description": "Demo Shopper Context Widget"
}

Note that the extensionID must match the value generated on the Extensions page in the administration interface. See Install the widget for more information.

Write the widget JavaScript

The following example shows the JavaScript for the sample Shopper Context Selector widget.

For general information on creating and uploading a custom widget, refer to Create a Widget.

/**
 * @fileoverview Shopper Context Selector.
 */
define(

  //-------------------------------------------------------------------
  // DEPENDENCIES
  //-------------------------------------------------------------------
  ['knockout', 'pubsub', 'ccConstants','notifier', 'CCi18n', 'storageApi',
 'viewModels/shopperContext'],

  //-------------------------------------------------------------------
  // MODULE DEFINITION
  //-------------------------------------------------------------------

  function(ko, pubsub, CCConstants, notifier, CCi18n, storageApi,
ShopperContext) {
    "use strict";
    return {
      WIDGET_ID:
        "shopperContextSelector",
      isReady: ko.observable(false),
      onLoad: function(widget) {
        var self = this;
        widget.shopperContextViewModel = ko.observable();
        widget.shopperContextViewModel(ShopperContext.getInstance());
        widget.shopperContextViewModel().
           getOrderDynamicPropertiesWithDefaultValues();
        $.Topic(pubsub.topicNames.USER_LOGIN_SUCCESSFUL).subscribe(function(){
          widget.shopperContextViewModel().populatePLGandCatalogData();
             });
        $.Topic(pubsub.topicNames.USER_LOGOUT_SUCCESSFUL).subscribe(function(){
          widget.isReady(false);
          window.location.reload();
        });
      },
      beforeAppear:function(page) {
        var widget = this;
        if (widget.user().loggedIn() != false) {
          widget.isReady(true);
        }else{
          widget.isReady(false);
        }
      },
   // Click handler for the Load Context button
      handleLoadContext: function (viewModel, event) {
        var widget = this;
        widget.shopperContextViewModel().populatePLGandCatalogData();
      },
     };
   }
);

Display the context switcher

The custom widget’s display.template file displays the context switcher that a shopper uses to pick a new context that will invoke the webhook.

<!-- ko if: (isReady) -->
<div class="container-fluid">
  <!-- ko if: $data.shopperContextViewModel().dynamicProperties().length > 0 -->
  <div class="row"  data-bind="foreach:
$data.shopperContextViewModel().dynamicProperties">
    <!-- ko if: (type === 'shortText' || type==='richText' || type==='number') -->
    <div class="col-md-12">
      <label data-bind="text: label"></label>
      <input type="text" data-
bind="value:$parent.shopperContextViewModel().shopperContext[id],
attr:{'id':id}"/>
    </div>
    <!-- /ko -->
    <!-- ko if: (type === 'checkbox') -->
    <div class="col-md-12">
      <label data-bind="text: label"></label>
      <input type="checkbox" data-
bind="checked:$parent.shopperContextViewModel().shopperContext[id],
attr:{'id':id}"/>
    </div>
    <!-- /ko -->
    <!-- ko if: (type == 'date') -->
    <div class="col-md-12">
      <label data-bind="text: label"></label>
      <input type="date" data-
bind="checked:$parent.shopperContextViewModel().shopperContext[id],
attr:{'id':id}"/>
    </div>
    <!-- /ko -->
  </div>
  <button data-bind="click: handleLoadContext"> <span data-bind="text:'Load
Context'"></span></button>
  <!-- /ko -->
</div>
<!-- /ko -->

Install the widget

To install the widget, perform the following tasks in the administration interface:

  1. Click the Settings icon.
  2. Click Extensions and display the Developer tab.
  3. Click Generate ID to generate an extension ID for the widget.
  4. Edit the widget’s ext.json file and set the extensionID property to the value generated in the previous step.
  5. Package the widget as a ZIP file. Use the structure described in Create the widget structure.
  6. Display the Installed tab and click Upload Extension. Select the ZIP file.
  7. Publish your changes.