Autocomplete tutorial

Initial page load

This tutorial will walk you through integrating the autocomplete feature and demonstrate interactions between various Luigi's Box services and APIs.

The autocomplete flow begins by the user entering the site at a title page. The included LBX script will automatically set an _lb cookie which will represent the transient user ID.

document.cookie.match(/_lb=(.*?);/)'})

Inspect the _lb cookie using browser developer tool or use the code above to read its value. If the cookie does not exist, ensure that the LBX script is included.

Load query suggestions

As the page loads, fetch the query suggestions using the Trending queries API.

Implementing this experience is not strictly necessary, but it will point user attention to search and increase search usage.

https://live.luigisbox.com/v2/trending_queries
  ?tracker_id=<tracker_id>

Tips

The trending queries are automatically learned by the system from the analytics events. When you are starting the development, there are probably no queries learned at this time and the API call will return an empty response. You can set up some query suggestions in the Luigi's Box application in the Search suggestions customization section.

Render query suggestions

The API call will give you back a list of queries. You can render these as typing suggestions or placeholder texts in the searchbox to nudge the user into using the search.

Example response from the Trending queries endpoint:

[
  {
    "title": "search and get 10% off"
  },
  {
    "title": "piano"
  },
  {
    "title": "casio"
  }
]

Tips

The trending queries are automatically learned by the system from the analytics events. When you are starting the development, there are probably no queries learned at this time and the API call will return an empty response. You can set up some query suggestions in the Luigi's Box application in the Search suggestions customization section.

When the user clicks into the searchbox, display the autocomplete popup immediately, showing recommendations. Call the Top items API endpoint to load recommendations for categories, brands, products and other types you have indexed.

https://live.luigisbox.com/v1/personalized_top_items
?tracker_id=<tracker_id>
&type=item:6,category:3,brand:3,query:3
&user_id=<transient_user_id>
&remove_fields=nested


  • type=item:6,category:3,brand:3,query:3 - list the object types you want to load and the sizes
  • user_id=<transient_user_id> - pass the value of the _lb cookie
  • remove_fields=nested - this will omit nested objects from the API response and will lead to faster loading times.

Tips

The selection of "top items" depends on analytics data. Without analytics, you will get back random products. To see more reasonable recommendations, consider uploading a log of historical purchases to prime the models.

Render initial recommendations in the autocomplete popup

Use the API response from the Top items endpoint to render suggestions for the users.

{
  "hits": [
    {
      "url": "PR-105359",
      "attributes": {
        "image_link": "https://cdn.myshoptet.com/usr/demoshop.luigisbox.com/user/shop/detail/1773108_veles-x-piano-key-dust-cover-124-x-15cm.jpg",
        "title": "Veles-X Piano Key Dust Cover 124 x 15cm",
        "price_eur_amount": 15.9,
        "web_url": "/veles-x-piano-key-dust-cover-124-x-15cm/"
      },
      "type": "item"
    },
    {
      "url": "PR-6552",
      "attributes": {
        "image_link": "https://cdn.myshoptet.com/usr/demoshop.luigisbox.com/user/shop/detail/1772742_gewa-900530.jpg",
        "title": "GEWA 900530",
        "price_eur_amount": 28.9,
        "web_url": "/gewa-900530/"
      },
      "type": "item"
    },
    {
      "url": "kalimba",
      "attributes": {
        "title": "kalimba"
      },
      "type": "query"
    },
    {
      "url": "ukulele",
      "attributes": {
        "title": "ukulele"
      },
      "type": "query"
    },
    {
      "url": "/ukulele-capos/",
      "attributes": {
        "title": "Ukulele Capos",
        "web_url": "/ukulele-capos/"
      },
      "type": "category"
    },
    {
      "url": "/smart-piano/",
      "attributes": {
        "title": "Smart piano",
        "web_url": "/smart-piano/"
      },
      "type": "brand"
    }
  ],
  "recommendation_id": "default"
}

(API response shortened for brevity)

Tips

Note that in the response, the top-level url field refers to object identities which is not necessarily an HTTP link. The exact details of the response depend on the data you have indexed. In general, the "url" property will be numerical identity and the web link will be in attributes.web_url.

Also note that the API response gives you back data for all the types requested in the API request. The object type is noted in the top-level type attribute.

Fire dataLayer event

After the top items recommendations have been rendered, fire a recommendation dataLayer event describing what you have just rendered.

dataLayer.push({
    event: "view_item_list",
    ecommerce: {
        item_list_name: "Recommendation",
        items: [
            {
                item_id: "PR-105359",
                item_name: "Veles-X Piano Key Dust Cover 124 x 15cm",
                index: 1,
                price: 15.9,
                type: "item"
            },
            {
                item_id: "PR-6552",
                item_name: "GEWA 900530",
                index: 3,
                price: 28.9,
                type: "item"
            },
            {
                item_id: "/ukulele-capos/",
                item_name: "Ukulele Capos",
                index: 3,
                type: "category"
            },
            {
                item_id: "/smart-piano/",
                item_name: "Smart piano",
                index: 4,
                type: "brand"
            }
        ],
        filters: {
            "RecommenderClientId": "autocomplete_popup"
        }
    }
});

(dataLayer event shortened for brevity)

Tips

  • Make sure that the item_id refers to the object identity (the url attribute in the top-level object data).
  • Provide data for all types, not just for products.
  • Make sure that the position index is unique for each item (independed of the type)

User starts typing

When the user types in a query into the searchbox, fire an API request to the autocomplete endpoint to fetch the suggestions for the popup.

GET https://live.luigisbox.com/autocomplete/v2
  ?q=digital+piano
  &type=item:7,category:3,brand:3,query:3
  &user_id=<transient_user_id>

  • q - pass the search phrase (value of the searchbox)
  • type=item:7,category:3,brand:3,query:3 - list the object types you want to load and the sizes
  • user_id=<transient_user_id> - pass the value of the _lb cookie

Render autocomplete/suggestions

The API response will include all the product data that you will use to render a popup or widget that shows the results.

{
  "hits": [
    {
      "url": "PR-15553",
      "attributes": {
        "image_link": "https://cdn.myshoptet.com/usr/demoshop.luigisbox.com/user/shop/detail/1774257_smart-piano-the-one-digital-piano.jpg",
        "title": "Smart <em>piano</em> The ONE <em>Digital</em> Piano",
        "title.untouched": "Smart piano The ONE Digital Piano",
        "price_amount": 629,
        "web_url": "/smart-piano-the-one-digital-piano/"
      },
      "type": "item"
    },
    {
      "url": "PR-76761",
      "attributes": {
        "image_link": "https://cdn.myshoptet.com/usr/demoshop.luigisbox.com/user/shop/detail/1784343_kurzweil-digital-piano.jpg",
        "title": "Kurzweil <em>Digital</em> <em>Piano</em>",
        "title.untouched": "Kurzweil Digital Piano",
        "price_amount": 890,
        "web_url": "/kurzweil-digital-piano/"
      },
      "type": "item"
    },
    {
      "url": "piano",
      "attributes": {
        "title": "<em>piano</em>",
        "title.untouched": "piano"
      },
      "type": "query"
    },
    {
      "url": "/digital-pianos/",
      "attributes": {
        "title": "<em>Digital</em> <em>Piano</em>s",
        "title.untouched": "Digital Pianos",
        "hierarchy": [
          "Musicians",
          "Keys"
        ],
        "web_url": "/digital-pianos/"
      },
      "type": "category"
    },
    {
      "url": "/smart-piano/",
      "attributes": {
        "title": "Smart piano",
        "web_url": "/smart-piano/"
      },
      "type": "brand"
    }
  ]
}

(API response shortened for brevity)

Tips

The API response will include <em> highlights in attributes.title. If you need access to the original title without highlight, use the attributes["title.untouched"] field.

Fire a dataLayer event for autocomplete

After the results have been rendered, fire a dataLayer event describing what you have just rendered.

dataLayer.push({
    event: "view_item_list",
    ecommerce: {
        item_list_name: "Autocomplete",
        search_term: "digital piano",
        items: [
            {
                item_id: "PR-15553",
                item_name: "Smart piano The ONE Digital Piano",
                index: 1,
                price: 629
            },
            {
                item_id: "PR-76761",
                item_name: "Kurzweil Digital Piano",
                index: 2,
                price: 890
            },
            {
                item_id: "/digital-pianos/",
                item_name: "Digital pianos",
                index: 3,
                type: "category"
            },
            {
                item_id: "/smart-piano/",
                item_name: "Smart piano",
                index: 4,
                type: "brand"
            }
        ]
    }
});

(dataLayer event shortened for brevity)

Tips

  • Make sure that the item_id refers to the object identity (the url attribute in the top-level object data).
  • Provide data for all types, not just for products.
  • Make sure that the position index is unique for each item (independed of the type)
  • When using the Autocomplete API to build the event, use the title.untouched attribute as the value for item_name as that includes the original title without highlights. If you use the title attribute, you will be reporting titles with <em> tags.

Fire dataLayer click event

When the user clicks on a result, immediately fire a dataLayer event.

dataLayer.push({
    event: "select_item",
    ecommerce: {
        items: [
            {
                item_id: "PR-76761",
            }
        ]
    }
});

Fire impression dataLayer event

When the product detail page loads, fire an impression dataLayer event.

dataLayer.push({
event: "view_item",
    ecommerce: {
        items: [
            {item_id: "PR-76761"}
        ]
    }
});

Fire add_to_cart event

When the user adds the product to cart, fire an add_to_cart dataLayer event.

dataLayer.push({
    event: "add_to_cart",
    ecommerce: {
        currency: "EUR",
        value: 890,
        items: [
            {item_id: "PR-76761"}
        ]
    }
});

Fixit rules integration

To provide deeper integration with Luigi's Box Fixit redirect rules, you can mark the redirect queries and you can provide early redirects to ensure smooth experience for the user.

{
  "hits": [
    {
      "url": "contact",
      "attributes": {
        "fixit_redirect_url": [
          "https://demoshop.luigisbox.com/contact-us/"
        ],
        "title": "<em>contact</em>",
        "title.untouched": "contact"
      },
      "type": "query"
    }
  ],
  "suggested_url": "https://demoshop.luigisbox.com/contact-us/?lb_redirected_from=contact"
}

(API response shortened for brevity)

Tips

  • If a query is found, for which a Fixit redirect rule is set up in Luigi's Box application, the query result (hit) will have a fixit_redirect_url attribute. This allows you to perhaps specifically visualize the query, as you can see in the illustrative image.
  • If submitting the query to search should cause a redirect because a Fixit redirect rule exists, the Autocomplete API endpoint response will include a suggested_url attribute, indicating the redirect URL.

Banner campaigns integration

To provide integration for the Banner campaigns feature obey the banner instructions in the campaigns attribute in the API response.

{
  "hits": [

  ],
  "campaigns": [
    {
      "id": 45,
      "target_url": "https://www.luigisbox.com",
      "banners": {
        "autocomplete_list": {
          "desktop_url": "https://cdn.example.com/uploads/banners/310x240.png",
          "mobile_url": "https://cdn.example.com/uploads/banners/420x240.png"
        }
      }
    }
  ]
}

(API response shortened for brevity)

User sign in

When the user signs in, the API calls needs to be adjusted slightly, since you now have a persistent user identity. By propagating this persistent identity to Luigi's Box, you will get more accurate personalization since the system will be able to aggregate user data across different devices and sessions.

Fire dataLayer customer_id event

dataLayer.push({
    event: "luigisbox.collector.customer_id",
    customer_id: "281827";
  },
});

Once you know the personalized user ID, emit a customer_id dataLayer event. It is safe to emit the event just once per session, but it will not cause any problems if you emit it more than once per session.

When loading the autocomplete recommendations on searchbox click, pass the persistent user ID instead of the transient user ID from the _lb cookie.

https://live.luigisbox.com/v1/personalized_top_items
?tracker_id=<tracker_id>
&type=item:6,category:3,brand:3,query:3
&user_id=<persistent_user_id>
&client_id=<transient_user_id>
&remove_fields=nested


  • user_id=<persistent_user_id> - pass the persistent user ID
  • client_id=<transient_user_id> - pass the value of the _lb cookie

Identified user starts typing

When the user types in a query into the searchbox, you will fire an API request to the autocomplete endpoint to fetch the suggestions for the popup, passing both transient and persistent user IDs.

GET https://live.luigisbox.com/autocomplete/v2
  ?q=digital+piano
  &type=item:7,category:3,brand:3,query:3
  &user_id=<persistent_user_id>
  &client_id=<transient_user_id>

  • user_id=<persistent_user_id> - pass the persistent user ID
  • client_id=<transient_user_id> - pass the value of the _lb cookie

Limit amount of data transferred

GET https://live.luigisbox.com/autocomplete/v2
  ?q=digital+piano
  &type=item:7,category:3,brand:3,query:3
  &hit_fields=product_id,title,price,image_link
  &remove_fields=nested
  &user_id=<transient_user_id>

To limit the amount of data transferred between systems, specify the hit_fields and/or remove_fields attribute in the API request. It is an array of result properties which will be included in the API response. By using this, you can significantly reduce the amount of data transfer and increase performance.

Show all steps