Use the Recommendations API

This is for:

Developer

In this tutorial, we will be calling the Recommendations API to power more advanced personalizations. We want to empower the marketer to control the content displayed within the recommendations.

By editing the fields.json file, we can expose controls that non-technical users can edit to make basic changes to the experience. Importantly, as a developer, you retain control over what can be edited.

For this tutorial, we will allow marketers to:

  • Modify the number of products in the carousel

  • Defined the recommendations strategy used

  • Have the ability to insert a product manually into the carousel to increase merchandiser control

Step 1: Creating the Custom experience

Select Experiences from the side menu. Then select New experience, Custom, and Choose

Enter a name for your experience in the field provided and select Create

Step 2: Editing the fields.json file

The first thing we want to do is set our variables within fields.json.

Open the code editor for the custom experience and select the fields.json from the side menu

Paste the following lines into the editor:

{
  "fields": [
    {
      "key": "title",
      "type": "String",
      "label": "Title",
      "groupId": "message",
      "required": true,
      "description": ""
    },
    {
      "key": "noOfProducts",
      "type": "Number",
      "label": "Number of Products generated by the api",
      "groupId": "message",
      "required": true,
      "description": ""
    },
    {
      "key": "strategy",
      "type": "String",
      "label": "What is the strategy you want to use for recommendations",
      "groupId": "message",
      "required": true,
      "description": "popular, pp1 or pp3"
    },
    {
      "key": "staticProduct",
      "type": "Boolean",
      "label": "Check to include a static product in the carousel",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    },
    {
      "key": "productImg",
      "type": "Image",
      "label": "Product Img",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    },
    {
      "key": "productImgLink",
      "type": "String",
      "label": "Product Img Link",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    },
    {
      "key": "productPrice",
      "type": "String",
      "label": "Product Price",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    },
    {
      "key": "productName",
      "type": "String",
      "label": "Product Name",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    },
    {
      "key": "productId",
      "type": "String",
      "label": "Product Id",
      "groupId": "staticProductArea",
      "required": true,
      "description": ""
    }
  ],
  "groups": [
    {
      "id": "message",
      "title": "Suggested products banner",
      "subtitle": "Choose the title and number of products."
    },
    {
      "id": "staticProductArea",
      "title": "Include a static product in the carousel"
    }
  ]
}

Note that we have 2 groups, 1 for the recommendations carousel and 1 for the static product.

Select Save and then exit the editor. You should now see the marketer controls

Step 3: Adding experience content

Make the following changes:

  • In Title, enter Don’t fancy this? Why not look at …​

  • in Number of Products generated by the api, enter 5

  • in What is the strategy you want to use for recommendations, enter pp1

  • Select the Check to include a static product in the carousel tickbox to include a static product in the carousel and use image:

https://s3.amazonaws.com/aliceandolivia-java/images/skus/alice_and_olivia_ODELIAMIDLENGTHDRESS_INDIGOBLACK_888819373795_PRODUCT_01--165030044.jpg
  • in Product Img Link, enter the link you want to use for the image

  • in Product Price, enter a price

  • in Product Name, enter a product name

  • in Product Id, enter a product Id

Select Save

Step 4: Adding triggers

Return to the code editor and select the trigger.js file from the side menu

Replace any content in the editor with the following lines:

module.exports = function triggers (options, cb) {
  const _ = require('slapdash')
  const createStash = require('@qubit/http-api-stash')
  const $ = window.jQuery
  const { trackingId, visitorId } = options.meta
  const { noOfProducts, staticProduct } = options.data
  const stashKey = 'viewedProductId'
  const strategyId = options.data.strategy
  const noRecsToRequest = staticProduct ? noOfProducts - 1 : noOfProducts
  const recommendationsUrl = 'https://recs.qubit.com/vc/recommend/2.0/'
  const stash = createStash('kv', trackingId, {
    namespace: trackingId,
    useVisitorId: true
  })

  options.uv.on('ecProduct', (e) => {
    const isProductPage = _.get(e, 'eventType') === 'detail'
    const { productId } = _.get(e, 'product')

    if (isProductPage && productId) {
      checkRecentlyViewed(productId)
    }
  }).replay()

  function checkRecentlyViewed (productId) {
    stash.get(stashKey).then((result) => {
      const products = JSON.parse(result)
      const productNotStored = products.indexOf(productId) === -1

      if (products.length === 3) {
        products.pop()
      }

      if (productNotStored) {
        products.unshift(productId)
      }

      updateRecentlyViewed(products)
    }).catch(() => {
      updateRecentlyViewed([productId])
    })
  }

  function updateRecentlyViewed (products) {
    stash.set(stashKey, JSON.stringify(products))
    getRecommendations(products)
  }

  function getRecommendations (products) {
    const url = recommendationsUrl + `${trackingId}?` + [
      `strategy=${strategyId}`,
      `id=${visitorId}`,
      `n=${noRecsToRequest}`
    ].join('&')

    const seed = JSON.stringify({
      h: products
    })

    $.post(url, seed, (recommendations) => {
      if (recommendations && recommendations.items) {
        options.state.set('recommendations', recommendations.items)
        cb(true)
      }
    })
  }
}

The example above performs 3 functions. Firstly, it checks if the visitor is on a product page, and if so get the product id. It then stores the visitor’s last 3 product Ids they viewed. Finally, it sends these product Ids to the Recommendations API.

TIP: These products are stored against the visitor’s cookie Id, you could easily set this to their user Id to enable cross-device recommendations.

Step 5: Adding package dependencies

The above code has package dependencies. We need to add these to our experience.

Select package.json from the side menu. Select Add a package

Search for and add the following packages:

  • slapdash ^1.3.3

  • @qubit/floating-panel ^1.0.0

  • @qubit/http-api-stash ^1.1.1

  • @qubit/image-carousel ^1.0.0

Step 6: Editing the variation.js file

Select variation.js from the side menu. Replace any content in the editor with the following lines:

module.exports = function variation (options) {
  const createPanel = require('@qubit/floating-panel')
  const createCarousel = require('@qubit/image-carousel')
  const recommendations = options.state.get('recommendations', recommendations)

  buildCarousel(recommendations)

  function buildCarousel (recommendations) {
    const panel = createPanel({ // Create the panel object, which will expose a DOM Element 'el'.
      showClose: true // Show a close button on this panel
    })
    // Turn the product list into an array of image objects for rendering
    const images = getImages(recommendations)

    const staticProduct = {
      src: options.data.productImg,
      url: options.data.productImgLink,
      currency: 'gbp',
      price: options.data.productPrice,
      title: options.data.productName,
      id: options.data.productId
    }

    if (options.data.staticProduct) {
      images.unshift(staticProduct)
    }

    const carousel = createCarousel({ // Create the carousel object to insert into the panel
      el: panel.el,
      images: images,
      title: options.data.title,
      numberOfDisplayedProducts: options.data.noOfProducts,
      imageClick: (i) => {
        window.location.href = recommendations[i].details.url
      }
    })

    // Invoke the carousel rendering
    carousel.render()

    function getImages (items) {
      return items.map((item) => {
        const details = item.details || {}

        return {
          src: details.image_url,
          url: details.url,
          currency: details.currency,
          price: details.unit_sale_price || details.unit_price,
          title: details.name,
          id: details.id
        }
      })
    }
  }
}

The above code performs 2 functions. Firstly, it builds a carousel of images using the image-carousel package. It inserts these images into a floating panel using the floating-panel package.

Select Save and preview the experience

Last updated: July 2018