Skip to main content

Handling Turbolinks

Fast Simon SDK allows handling turbolinks — redirects based on specific queries — in two key scenarios: Instant Search (Autocomplete) and Direct Navigation (fullTextSearch).

In autocomplete results, you can extract and display turbolinks from the response and optionally use them for redirection or display as suggestions.

Here’s a sample setup:

window.FastSimonSDK.instantSearch({
query: searchTerm,
callback: (response) => {
console.log(response);
displayAutocomplete(response.payload, searchTerm);
}
});

Within the displayAutocomplete function (which receives the payload), you can extract the turbolinks and optionally save the matching URL for later redirection:

function displayAutocomplete(payload, searchTerm) {
let turboLinkUrl = null;

payload.turbolinks.forEach(turbolink => {
const turboLink = document.createElement('a');
turboLink.href = turbolink.u;
turboLink.innerText = turbolink.l;
turboLink.target = '_blank'; // Or handle programmatic redirect

if (turbolink.l.toLowerCase() === searchTerm.toLowerCase()) {
turboLinkUrl = turbolink.u;
}

// Append to your suggestions UI
linksContainer.appendChild(turboLink);
});

// Optional redirect logic
if (turboLinkUrl) {
window.location.href = turboLinkUrl;
}
}

This allows either showing the turbolinks as clickable results or redirecting when the user enters an exact match.


2. Direct Navigation to Search Page (fullTextSearch)

When a shopper navigates directly to the search results page with a query (e.g. ?q=gift card), fullTextSearch may resolve a turbolink for that term. Using the recommended two-callback setup, handle it at the top of onProductsLoaded — check response.turbolink and redirect before rendering products:

window.FastSimonSDK.fullTextSearch({
term: term,
page: this.page,
productsPerPage: 48,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
onFacetsLoaded: (response) => {
this.renderFacets(response.facets);
},
onProductsLoaded: (response) => {
// Turbolink redirect — check before rendering products
if (response.turbolink?.u) {
window.location.href = response.turbolink.u;
return;
}

this.renderProducts(response.products);

// Log the search event
window.FastSimonSDK.event({
eventName: window.FastSimonEventName.SearchPerformed,
data: {
query: term,
categoryID: category_id,
narrowBy: this.narrowBy,
sortBy: this.sortBy,
products: response.products.map(({ id }) => id).toString(),
rescount: response.totalResults,
pagenum: Math.ceil(response.totalResults / 48)
}
});
}
});
Callback shape

The split callbacks (onProductsLoaded / onFacetsLoaded) receive the result object directly — read response.turbolink, response.products, response.facets (not response.payload.*). The payload envelope only applies to the single unified callback.

A turbolink can reach the search page two ways:

  • Server-resolved (post-network): the search backend returns a turbolink for the term; it arrives in onProductsLoaded as response.turbolink. This is the case you must handle, and the example above covers it.
  • Client-matched (pre-network, optional optimization): if you use the single unified callback instead of the split callbacks, and the term matches a turbolink already cached on the client, the SDK fires callback early with action: "turbolink" and payload.turbolink — saving a round-trip. This early event is delivered only through the unified callback.
caution

Don't rely on action === "turbolink" alone. With the split callbacks, that early event is never delivered — the turbolink arrives as response.turbolink in onProductsLoaded. If you only check the action, server-resolved turbolinks are missed and the shopper lands on the generic results page instead of being redirected.

{
"query": "gift card",
"products": [],
"totalResults": 0,
"turbolink": {
"l": "gift card",
"u": "https://www.example.com/collections/gift-card",
"t": ""
}
}

Whenever response.turbolink.u is present, redirect to it.