smart_suggest_new

smart_suggest_new

This is an old revision of the document!


This information is also available as API specification.

Smart Suggest customization

Basic Usage


Standard Integration

Integrate a JavaScript snippet you can find in the customer account on all pages of the site and you can get started with FINDOLOGIC's standard Smart Suggest implementation.


Advanced functionality


(User)groups


Groups are a feature for services using a CSV export that allows limiting the visibility of certain products to specific groups of people. The IDs of such groups must be part of the export. To distinguish between groups in Smart Suggest and search results, make sure an element as such is present in thesearch form:

<input type="hidden" name="group[]" value="GROUP_ID">

Usergroups are a feature for services using an XML export that allows not only limiting visibility, but also displaying different information to different people on the same product. Use a different input tag from above (not necessary for Direct Integration):

<input type="hidden" name="usergroup" value="USERGROUP">

It's also necessary to add the usergroup to the FINDOLOGIC JS snippet as such:

// ...
var mainUrl = "https://cdn.findologic.com/static/MD5_HASH_OF_SHOPKEY/main.js?usergrouphash=USERGROUP";
// ...


Available on demand


For the following functionality, please contact support to have it enabled:

  • Showing prices for product suggestions.
  • Showing unit price for product suggestions (e.g. 9.90 €/g).
  • Enabling a Smart Suggest proxy on the site's server and settings its URL.


Using custom changes


Hookpoints and custom templates (see details below) can be used for advanced changes of appearance and displaying additional data, as long as such data is part of the Smart Suggest response as documented in Types > SmartSuggestResponse.

It is also possible to show additional information if the Smart Suggest request is not sent directly to FINDOLOGIC, but to a proxy on the shop server instead. The proxy forwards the request to FINDOLOGIC and extends the response with custom information.

Be advised that introducing a proxy can increase latency significantly because the request takes an additional detour, is parsed and serialized once more, and it can also take some time to generate the data that is used to enrich the response. Choose this solution only if the performance drop is acceptable in exchange for very important functionality.


Fully custom client-side implementation


For maximum flexibility, it is possible to create a fully custom implementation of Smart Suggest's client side visualization. For information on how to query suggestions from FINDOLOGIC, check the API docs below.


Extending via hookpoints


Basic

When extending the Smart Suggest via hookpoints, FINDOLOGIC cannot ensure the quality of the product anymore. Therefore, our technical support will not provide service for issues which are caused by adaptions of the Smart Suggest.
The examples in the sections below assume the context of the listener function!


Available objects


The event object e exposes the following properties of interest:

  • e.detail.flAutocomplete: The main Smart Suggest object.
  • e.detail.fljQuery: The jQuery version bundled with FINDOLOGIC scripts.
  • e.detail.flAutocompleteUiWidget: Extended jQuery UI widget that handles Smart Suggest visualization.
  • e.detail.autocompleteUlElement: The jQuery-selected Smart Suggest root element.


Available methods


Via the objects listed above, it's possible to override default behavior.

e.flAutocompleteUiWidget.renderResultItem(item)

This method receives item data and must return a jQuery-wrapped DOM fragment that is used as suggestion list item. There are two ways to implement a custom suggestion visualization. The examples for the different approaches produce equivalent output.


Building item markup manually

Building elements safely using jQuery:

e.detail.flAutocompleteUiWidget.renderResultItem = function (item) {
  // The basic structure should always be an <a> element wrapped in a <li>
  // element.
  var container = jQuery('<li>', {
    'class': item.block
  });
  var link = jQuery('<a>');
  container.append(link);
 
  link.html(this.buildLabel(item));
 
  // For selection to work, a data attribute must be set in all cases:
  container.data('ui-autocomplete-item', {
    item: item,
    config: this.options.shopConfig
  });
 
  return container;
};

Simpler approach using concatenation and one-time parsing:

e.detail.flAutocompleteUiWidget.renderResultItem = function (item) {
  // The basic structure should always be an <a> element wrapped in a <li>
  // element.
  var container = jQuery('<li>', {
    'class': item.block
  });
 
  var highlightedLabel = this.buildLabel(item);
 
  container.html('<a>' + highlightedLabel + '</a>');
 
  // For selection to work, a data attribute must be set in all cases:
  container.data('ui-autocomplete-item', {
    item: item,
    config: this.options.shopConfig
  });
 
  return container;
};


Using Handlebars.js

This method is not recommended, because if can perform poorly on low power devices.

The page needs to contain a script tag containing the template, like this:

<script id="TEMPLATE_ID" type="text/x-handlebars-template">
<li class="fl-item-{{ item.block }}">
  <a>
    {{{ labelHighlighted }}}
  </a>
</li>
</script> 

Note that the basic structure should always be a <a> element within a <li> element.

The rendering method should now look like this:

e.detail.flAutocompleteUiWidget.renderResultItem = function (item) {
  // Build the context object that is used by Handlebars.js for rendering. The
  // defined properties are available directly in the template.
  var context = {
    item: item,
    labelHighlighted: this.buildLabel(item),
    config: this.options.shopConfig
  };
 
  // Render the template specified by TEMPLATE_ID - this returns a
  // jQuery-wrapped DOM fragment.
  var container = this._renderItem.call(this, context, 'TEMPLATE_ID');
 
  // For selection to work, a data attribute must be set in all cases:
  container.data('ui-autocomplete-item', item);
 
  return container;
};


e.detail.flAutocomplete.afterRendering()

This method is useful for modifying Smart Suggest output once its layout is complete, e.g. for repositioning the container (e.detail.autocompleteUlElement).

Example:

e.detail.flAutocomplete.afterRendering = function () {
  e.detail.autocompleteUlElement.css({
    position: 'absolute',
    left: 100,
    top: 50
  });
};


e.flAutocomplete.selectItem(event, ui)

This method allows custom behavior when a suggestion is clicked.

Note that overriding this method replaces everything that happens by default when clicking a suggestion, including sending a search, and tracking the request with Google Analytics (if available). Either make sure all of this happens manually, or call the original method after your custom logic as illustrated below:

var originalSelectItem = e.detail.flAutocomplete.selectItem;
e.detail.flAutocomplete.selectItem = function (event, ui) {
  // The current query in the search field:
  var searchTerm = event.target.value;
 
  // The item being selected:
  var item = ui.item;
  // Note that the properties of ui.item are a superset of the suggestion object
  // returned by the Smart Suggest API, so it can contain things like URLs for
  // promotions and products. See _Types > SmartSuggestResponse_ for details.
 
  // The search form Smart Suggest acts on:
  var searchForm = e.detail.flAutocomplete.getFormByEventTarget(event);
 
  // The text of the selected item:
  var selectedText = ui.item.label;
 
  // Do whatever custom thing you want to do here.
 
  // Finally, make sure that the default selection logic is executed.
  originalSelectItem.call(e.detail.flAutocomplete, event, ui);
};

Query parameter multivalue syntax


Some query parameters allow multiple values. In such cases, PHP syntax for query parameter arrays is used. Generally, the name of the parameter is succeeded by square brackets, like such:

...?autocompleteblocks[]=suggest&autocompleteblocks[]=cat

Optionally, an index may be specified within the square brackets, without affecting the response:

...?group[0]=foo&group[1]=bar

Using empty square brackets and indexes interchangeably does not affect the response either.


Type


Smart Suggest Response

A list of suggestions, which is the response to a successful Smart Suggest request. Can be an emtpy array in case the query does not yield any useful suggestions.

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Smart Suggest response",
  "description": "Structure of responses served by FINDOLOGIC Smart Suggest.",
  "type": "array",
  "minItems": 0,
  "items": {
    "type": "object",
    "description": "A single suggestion. All properties are returned, even if they serve no purpose for the type of suggestion. In that case, they are null.",
    "properties": {
      "label": {
        "type": "string",
        "description": "The display label of a suggestion. Should always be visualized."
      },
      "block": {
        "enum": [
          "suggest",
          "landingpage",
          "cat",
          "vendor",
          "product",
          "promotion"
        ],
        "description": "The type of suggestion: suggestion (completion of the input query), landingpage (a configured content page), cat (category matching the input query), vendor (brand or manufacturer matching the input query), product (products with a title that matches the input query), promotion (a maximum of one configured promotion)"
      },
      "frequency": {
        "type": [
          "string",
          "null"
        ],
        "pattern": "^\\d+$",
        "description": "Number of products matching the suggestion. Is always null for promotion- and landingpage suggestions."
      },
      "price": {
        "type": [
          "number",
          "null"
        ],
        "description": ""
      },
      "basePrice": {
        "type": [
          "number",
          "null"
        ],
        "description": ""
      },
      "basePriceUnit": {
        "type": [
          "number",
          "null"
        ],
        "description": ""
      },
      "identifier": {
        "type": [
          "string",
          "null"
        ],
        "description": "Export ID of the product. Is only set for product suggestions."
      },
      "url": {
        "type": [
          "string",
          "null"
        ],
        "pattern": "^https?://",
        "description": "The URL to follow when clicking on a suggestion. This is only relevant for promotion- landingpage- and product suggestions."
      },
      "imageUrl": {
        "type": [
          "string",
          "null"
        ],
        "pattern": "^$|^https?://",
        "description": "The URL of the primary product image. This is only relevant for product- and vendor suggestions. The value is null for promotion and langingpage suggestions, and an empty string for query-, cat- and vendor suggestions."
      },
      "ordernumber": {
        "type": [
          "string",
          "null"
        ],
        "description": "A product's ordernumber. If multiple ones are exported per product, the first of those is shown. This property is only set for product suggestions."
      }
    },
    "required": [
      "label",
      "block",
      "frequency",
      "price",
      "basePrice",
      "basePriceUnit",
      "identifier",
      "url",
      "imageUrl"
    ],
    "additionalProperties": false
  }
}


/autocomplete.php


Request


Query Parameters

shopkey required, matching ^[A-F0-9]{32}$ string

  • Unordered List ItemShopkey of the service for which suggestions should be generated.

query required, at least 1 characters string

  • The user input for which suggestions are generated.

autoq at least 1 characters string

  • Alternative to query. Takes precedence, if used.

count between 1-50, default: 10 integer

  • Number of suggestions to make. Note that if multiple blocks are suggested, this number is divided between the blocks.
  • If the maximum value is exceeded, the value provided the request is overridden silently.

autocompleteblocks[] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

  • Allows overriding the blocks that are configured to be displayed in the customer account.
  • See Query parameter multivalue syntax above for examples on how this parameter can receive multiple values.
  • Note that ordernumber is a virtual block to enable ordernumber-based product suggestions.

autocompleteblocks[1] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[2] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[3] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[4] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[5] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[6] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

autocompleteblocks[7] one of (suggest, landingpage, cat, vendor, ordernumber, product, promotion) string

group[] string

  • Unordered List ItemIndicates which groups' products are used for generating suggestions. This parameter is only relevant in case group information is exported.
  • See Query parameter multivalue syntax above for examples on how this parameter can receive multiple values.

group[1] string

group[2] string

group[3] string

usergrouphash string

  • Indicates which usergroup's products are used for generating suggestions. This parameter is only relevant in case usergroup information is exported.
  • Note that, other than group, this parameter accepts only one value.

multishop_id integer

  • Required for PlentyMarkets shops. Has no effect for other integrations.

callback string

  • Name of the callback that's called with the actual response, in case of using JSONP.
  • Note: The response schema only applies to the parameter passed to the callback called in the JSONP response. For instance, when requesting with callback=foobar , then an empty response would look like foobar([]) , as oppposed to [].

Response


Status 200


Headers

Access-Control-Allow-Methods string

Enables CORS for GET requests. Allowing OPTIONS is required for CORS to be possible at all. Note that in case CORS support is not possible, the callback parameter allows JSONP requests.

Access-Control-Allow-Origin string

Allows CORS requests from any site.

Body application/json

Examples:

Generic

[]

Empty

[]

Status 500


Body text/plain

Examples:

Missing Shopkey

dead: No shopkey submitted

Empty query

No query given or query empty

Bad type

Unknown autocomplete type

The Smart Suggest styles can be overwritten by the CSS from the shop.
Here you can find some examples for style selectors in order to style basic stuff.

Selectors

The following selectors give a general hint in how to style product placements in the Smart Suggest.

.fl-autocomplete li.ui-menu-item[data-fl-product-placement] a div {
   /* Styles here.. */
}

Style all product placements text

.fl-autocomplete li.ui-menu-item[data-fl-product-placement] a div {
   /* Styles here.. */
}

Style a certain product placement

.fl-autocomplete li.ui-menu-item[data-fl-product-placement="New shoe"] a div {
   /* Styles here.. */
}

Add a badge to a certain product placement

.fl-autocomplete li.ui-menu-item[data-fl-product-placement="New"] a div::after {
   /* Styles here.. */
}


Live examples

The following examples will show the code and the result in a live shop visually.


All product placements should have an fading background

.fl-autocomplete li.ui-menu-item[data-fl-product-placement] {
    background: linear-gradient(to right, #ffffff, #ffc0cb); /* white to pink */
}
/* Optional hover color change for product placements */
.fl-autocomplete li.ui-menu-item[data-fl-product-placement] a.ui-state-focus {
    background-color: #ffced7; /* Light pink */
}


Give all products from the product placement "New" a badge

/* Product placement "New" */
.fl-autocomplete li.ui-menu-item[data-fl-product-placement="New"] a div.col.label::after {
   content: "New"; /* Badge name */
    float: right;
    transform: rotate(-15deg); /* Rotation */
    font-weight: 700; /* Bold text */
    line-height: 1;
    color: #fff; /* Text color white */
    text-align: center;
    white-space: nowrap;
    vertical-align: baseline;
    border-radius: .25em;
    background-color: #ff0000; /* Badge color red */
    padding: 4px;
    margin: 1em; /* Horizontal center */
}


If you need any help with stylings, please contact our technical support.