DEV Community

Sahil Khurana
Sahil Khurana

Posted on • Originally published at innostax.com

Product Recommendations with Nosto: A Developer's Guide

"Customers who bought this also bought…" sounds like a trivial widget until you're the one building it. Real recommendation logic — behavioral data, real-time personalization, A/B testing, fallback states — is not something you want to hand-roll. That's the gap Nosto fills, and this guide covers what actually goes into wiring it up.


What Nosto Is Doing Under the Hood

Nosto is a commerce personalization platform. You feed it a product catalog and behavioral events (views, cart adds, purchases), and it returns recommendation slots — "Bestsellers," "Recently Viewed," "Customers Also Bought" — tailored per visitor. The integration has two halves: getting data into Nosto, and rendering recommendations from Nosto on your storefront.

💡 Pro tip: Recommendations are only as good as the event data feeding them. A broken tracking snippet silently degrades personalization quality — it won't throw errors, it'll just quietly serve generic bestseller lists to everyone.


Installing the Tracking Script

Every page needs Nosto's base tracking snippet loaded before other scripts:

<script type="text/javascript" src="https://connect.nosto.com/embed/shopify/YOUR_ACCOUNT_ID"></script>
Enter fullscreen mode Exit fullscreen mode

For non-Shopify stacks, use the platform-agnostic JS API instead:

window.nostojs(api => {
  api.defaultSession()
    .viewPage('/products/blue-running-shoes')
    .load();
});
Enter fullscreen mode Exit fullscreen mode

defaultSession() starts (or resumes) a visitor session; .load() sends the event and triggers Nosto to compute updated recommendations.


Sending Product and Category Events

Nosto's personalization engine runs on event signals. The three you'll implement first:

// Product page view
api.defaultSession()
  .viewProduct('SKU12345')
  .load();

// Category / listing page view
api.defaultSession()
  .viewCategory('/collections/running-shoes')
  .load();

// Add to cart
api.defaultSession()
  .addSkuToCart('SKU12345', 1)
  .load();
Enter fullscreen mode Exit fullscreen mode

Each call updates the visitor's session profile, which is what Nosto uses to personalize the next set of recommendations it returns.


Rendering a Recommendation Slot

Recommendation placements are just divs with a designated id, mapped to a slot you configure in the Nosto admin:

<div class="nosto_element" id="frontpage-nosto-1"></div>
Enter fullscreen mode Exit fullscreen mode

Nosto's script scans the page for these elements and injects the recommendation markup — product cards, images, prices — automatically. You control the layout of those cards via a template editor in the Nosto admin, not in your own codebase.

api.defaultSession()
  .setPlacements(['frontpage-nosto-1'])
  .load();
Enter fullscreen mode Exit fullscreen mode

If you're building a custom storefront (headless commerce, React/Vue frontends), you can skip the DOM-injection model entirely and fetch recommendation data as JSON:

api.recommendation('frontpage-nosto-1')
  .then(response => {
    renderCustomCarousel(response.products);
  });
Enter fullscreen mode Exit fullscreen mode

Handling the Empty State

New visitors with no session history, or products with thin behavioral data, won't have personalized recommendations to serve. Always configure a fallback:

  • Bestsellers or trending items as a catalog-wide default
  • A minimum data threshold in the Nosto admin before a slot activates
  • A loading skeleton rather than an empty div, since recommendation data loads asynchronously after initial page render

Testing Without Polluting Production Data

Nosto weights its models on real traffic, so testing against your live account can skew recommendations for real shoppers. Two practical guardrails:

  • Use a separate staging account ID for development, not the production one
  • If you must test on production, use Nosto's preview/test mode headers so test sessions are excluded from the personalization model

Where This Gets Non-Trivial

The basic setup above gets recommendations on the page. The parts that take real engineering time:

  • Data feed accuracy — Nosto ingests your product catalog on a schedule; stale pricing or inventory in the feed shows up directly in recommendation cards
  • SPA navigation — single-page apps don't trigger full page loads, so you need to manually call .load() on route changes or Nosto's session state goes stale
  • Multi-currency / multi-store — each storefront variant typically needs its own Nosto account or careful session scoping

Have you integrated Nosto (or a similar personalization engine) into a headless storefront? What was the trickiest part — the event tracking or the rendering layer? Drop your experience in the comments. 👇

#ecommerce #javascript #webdev #tutorial

Top comments (0)