Handling Turbolinks
Fast Simon SDK allows handling turbolinks — redirects based on specific queries — in two key scenarios: Instant Search (Autocomplete) and Direct Navigation (fullTextSearch).
1. Autocomplete (Top Search Bar)
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)
}
});
}
});
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
onProductsLoadedasresponse.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
callbackinstead of the split callbacks, and the term matches a turbolink already cached on the client, the SDK firescallbackearly withaction: "turbolink"andpayload.turbolink— saving a round-trip. This early event is delivered only through the unifiedcallback.
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.
Example turbolink result (delivered to onProductsLoaded)
{
"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.