How can we help?

First-Visit Personalisation

Overview

First-Visit Personalization extends personalized onsite experiences to visitors who are unknown or not yet identified. This feature evaluates browsing behavior in real time and returns tailored product recommendations that can be rendered in carousels, landing pages, and other onsite experiences.

By aggregating data across all site browse and purchase behavior, a default recommendation on the first page visit is continuously refined with every subsequent browse and cart event. This allows you to deliver relevant recommendations from the very first interaction, and improve relevance as the visitor continues to engage.

Common use cases include “Recommended for You” product carousels, personalized recommendations in chatbots, and dynamic landing pages that update based on real-time behavior.

Contact your CSM to begin using First-Visit Personalization.


How it works

First-Visit Personalization implementation is greatly simplified via the Product Carousel SDK, a lightweight JavaScript library that fetches and renders product recommendations.

At a high level:

  1. You install the Product Carousel SDK on your website.
  2. You place a container element where you want recommendations to appear.
  3. You initialize the SDK and call the recommendations endpoint (/recommend/products) with your account and product IDs (or let the SDK infer them from events).
  4. The SDK renders a responsive, customizable product carousel and updates as new browse and cart events occur.

Integration typically takes less than 10 minutes and requires minimal engineering effort. Alternatively, recommended Product IDs can be retrieved directly from the provided API and used as the basis for a tailored web experience.

Ensure your site is configured to send browse and cart events to Cordial using the track.js library. This forms the basis for aggregate and visitor-specific recommendations.


Initial setup

Option 1: Script loader pattern

Step 1: Add the SDK to your website.

Copy and paste this snippet into your HTML page:

<script>(function(P,R,O,D,U,C,T){  P.ProductCarouselObject=U,P[U]=P[U]||function(){(P[U].q=P[U].q||[]).push(arguments)};  P[U].l=1*new Date,P[U].q=[],C=R.createElement(O);  T=R.getElementsByTagName(O)[0],C.async=1,C.src=D,T.parentNode.insertBefore(C,T);})(window, document, 'script', 'https://site-sdk.cordial.io/prod-rec/$DATE/$COMMIT_SHA/product-carousel-sdk.umd.js', 'ProductCarousel');</script>

Step 2: Add a container element.

Place this <div> where you want the carousel to appear:

<div id="my-carousel"></div>

Step 3: Initialize and load recommendations.

<script>  // Initialize the carousel  ProductCarousel('init', {    containerId: 'anonymous_prod_rec',    apiEndpoint: 'https://infer.apps.cordial.io/recommend/products',    useCORSProxy: true,    eventNames: ['cart', 'productView'],    onProductClick: (product) => {      if(product.url) {        window.location.href = `${product.url}`;      }      console.log(product);    },    theme: {      primaryColor: '#007bff',      backgroundColor: 'transparent',      borderRadius: '0px',      cardShadow: 'none',      priceColor: '#6a6a6a'    },    showNavigation: true,  });    // Load recommendations with callback  ProductCarousel('loadRecommendations', {    account: 'speakercity',    product_ids: (() => {        try {            return JSON.parse(localStorage.getItem('productIDs') || '[]');        } catch (e) {            console.error('Failed to parse productIDs from localStorage:', e);            return [];        }    })()  }, function(error, response) {    if (error) {        console.error('Failed to load recommendations:', error);        return;    }    console.log('Loaded', response.recommendations.length, 'recommendations');  });</script>

Once this is in place, your anonymous product carousel is live and will react to browse and cart activity.


Option 2: Direct script include

If you prefer a more traditional script include and promise-based API, use this option.

<!-- Include the SDK directly --><script src="https://site-sdk.cordial.io/prod-rec/$DATE/$COMMIT_SHA/product-carousel-sdk.umd.js"></script><!-- Add a container --><div id="my-carousel"></div><!-- Initialize --><script>  // Initialize SDK  const sdk = ProductCarouselSDK.init({    containerId: 'my-carousel',    apiEndpoint: 'https://infer.apps.cordial.io/recommend/products'  });  // Load recommendations  sdk.then(sdkInstance => {    sdkInstance.loadRecommendations({      account: 'speakercity',      product_ids: (() => {        try {            return JSON.parse(localStorage.getItem('productIDs') || '[]');        } catch (e) {            console.error('Failed to parse productIDs from localStorage:', e);            return [];        }      })()    });  });</script>

Customizing the carousel

The Product Carousel SDK is fully configurable so you can align it with your brand and UX.

Basic customization

Use simple configuration options to control display and behavior:

<script>ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',    // Display options  showPrice: true,  showDescription: true,  maxDescriptionLength: 150,  imageAspectRatio: '1:1',    // Carousel behavior  autoPlay: true,  autoPlayInterval: 5000,  itemsToShow: 4,  showNavigation: true,  showDots: true,    // Brand colors  theme: {    primaryColor: '#007bff',    backgroundColor: '#ffffff',    borderRadius: '12px',    fontFamily: 'Arial, sans-serif'  }});</script>

Advanced theming

For more granular control over colors, typography, and layout:

ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',  theme: {    // Colors    primaryColor: '#007bff',    textColor: '#333333',    priceColor: '#28a745',    descriptionColor: '#6c757d',    backgroundColor: '#f8f9fa',        // Card styling    cardBackground: '#ffffff',    cardBorder: '1px solid #e9ecef',    cardShadow: '0 4px 6px rgba(0,0,0,0.1)',    borderRadius: '12px',        // Typography    fontFamily: 'Inter, sans-serif',    titleFontSize: '16px',    titleFontWeight: 600,    titleAlign: 'left',    priceFontSize: '18px',    priceFontWeight: 700,    priceAlign: 'right',    descriptionFontSize: '14px',    descriptionAlign: 'center'  }});

Mobile responsiveness

Configure layouts for different devices:

ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',  responsive: {    mobile: { itemsToShow: 1 },    tablet: { itemsToShow: 2 },    desktop: { itemsToShow: 4 }  }});

Integration examples

These examples show how to embed First-Visit Personalization in common site experiences.

Example 1: Product detail page

<h2>You May Also Like</h2><div id="related-products"></div><script>ProductCarousel('init', {  containerId: 'related-products',  apiEndpoint: 'https://api.example.com',  itemsToShow: 4,  theme: { primaryColor: '#ff6b6b' }});ProductCarousel('loadRecommendations', {  account: 'your-account',  product_ids: ['<%= current_product_id %>']}, function(error, response) {  if (error) console.error('Error:', error);});</script>

Example 2: Cart page

<h2>Frequently Bought Together</h2><div id="cart-recommendations"></div><script>var cartProductIds = ['prod1', 'prod2']; // from your cartProductCarousel('init', {  containerId: 'cart-recommendations',  apiEndpoint: 'https://api.example.com',  itemsToShow: 3,  showDescription: false});ProductCarousel('loadRecommendations', {  account: 'your-account',  product_ids: cartProductIds});</script>

Example 3: Homepage recommendations

<h2>Recommended For You</h2><div id="homepage-carousel"></div><script>ProductCarousel('init', {  containerId: 'homepage-carousel',  apiEndpoint: 'https://api.example.com',  autoPlay: true,  autoPlayInterval: 3000,  itemsToShow: 5,  theme: {    primaryColor: '#4CAF50',    borderRadius: '8px'  }});ProductCarousel('loadRecommendations', {  account: 'your-account',  product_ids: [] // empty for general recommendations});</script>

Example 4: Custom product click handler

ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',  onProductClick: function(product) {    // Track analytics    gtag('event', 'product_click', {      product_id: product.productID,      product_name: product.productName,      price: product.price    });        // Navigate to product page    window.location.href = '/products/' + product.productID;  }});

Data attribute configuration

For simple integrations, you can configure the carousel directly in HTML. The SDK will automatically initialize any element with the product-carousel-sdk class.

<div class="product-carousel-sdk"     id="carousel-1"     data-api-endpoint="https://api.example.com"     data-auto-play="true"     data-auto-play-interval="3000"     data-show-navigation="true"     data-show-dots="true"     data-items-to-show="3"     data-primary-color="#28a745"     data-background-color="#f8f9fa"     data-text-color="#333333"     data-border-radius="12px"     data-font-family="Arial, sans-serif"></div>

Key data attributes include:

  • data-api-endpoint: API endpoint URL
  • data-auto-play: enable auto-play ("true" / "false")
  • data-items-to-show: number of items visible at once
  • Theme attributes such as data-primary-colordata-background-colordata-text-colordata-border-radius, and data-font-family.

JavaScript-only configuration

Some options are only available in JavaScript (not via data attributes), including:

  • Display options: showPriceshowDescriptionmaxDescriptionLengthimageAspectRatio
  • Typography alignment and font weights/sizes
  • Advanced theme controls: cardBackgroundcardBordercardShadowbuttonColorpriceColor
  • Callbacks: onProductClick
  • Responsive configuration
  • Event configuration: eventTypeseventNames
  • Custom text messages: loadingTexterrorTextnoProductsText

Example:

const sdk = ProductCarouselSDK.create('my-carousel');await sdk.init({  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',  showPrice: true,  showDescription: false,  onProductClick: (product) => {    window.location.href = '/products/' + product.productID;  },  theme: {    titleAlign: 'left',    priceAlign: 'right'  }});

Event and data model (BroadcastChannel integration)

The SDK can listen to the x-crdl BroadcastChannel for product interaction events and automatically build up the context used for recommendations.

When enabled, the SDK:

  • Listens for configured eventTypes and eventNames (for example, ['event'] and ['cart', 'productView']).
  • Extracts product IDs from those events.
  • Stores up to 100 recent product IDs in localStorage.productIDs.

Configuration:

ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com',  eventTypes: ['event'],  eventNames: ['cart', 'productView']});

Broadcasting events from elsewhere in your application:

const channel = new BroadcastChannel('x-crdl');channel.postMessage({  action: ['event', 'cart', {    productID: 'PROD-123',    quantity: 1  }]});channel.postMessage({  action: ['event', 'productView', {    productID: 'PROD-456'  }]});

The SDK will automatically capture and store these product IDs, which can then be passed to /recommend/products.


API: Get product recommendations

First-Visit Personalization uses the recommendations API to fetch products.

Base URLhttps://infer.apps.cordial.io
EndpointPOST /recommend/products
Content-Typeapplication/json

Request body

{  "account": "speakercity",  "product_ids": [    "1",    "2"  ]}
  • account (string, required): client account identifier.
  • product_ids (array, required): seed product IDs used to generate recommendations (for example, items in cart or recently viewed).

cURL example:

curl --location --request POST 'https://infer.apps.cordial.io/recommend/products' \  --header 'Content-Type: application/json' \  --data-raw '{    "account": "speakercity",    "product_ids": ["1", "2"]  }'

Response schema

The API returns a JSON object with a recommendations array and optional metadata:

  • recommendations[]: list of product objects
    • product_id (string, required)
    • score (float, required)
    • confidence (float, required)
    • category (string, optional)
    • price (float, optional)
    • name (string, required)
    • description (string, optional)
    • url (string, required)
    • image_urls (array, optional)
    • total_quantity (integer, optional)
    • variants (object or null)
  • extra (array, optional): additional metadata tags (for example, ["verified"]).

Example response:

{  "recommendations": [    {      "product_id": "1889075",      "score": 100.0,      "confidence": 1.0,      "category": "TVs",      "price": 713.95,      "name": "65 inch Class U6 Series Mini-LED ULED 4K Smart Google TV - 65U6N",      "description": "Hisense's 65 inch Class U6 Series Mini-LED ULED 4K Smart Google TV - 65U6N brings a perfect mix of function and style to your everyday routine.",      "url": "https://store.cordialthreads.com/collections/tvs/products/hisense-65-inch-class-u6-series-mini-led-uled-4k-smart-google-tv-65u6n",      "image_urls": [        "https://cdn.shopify.com/s/files/1/0592/9789/0510/files/28537855_fpx.jpg?v=1747713588"      ],      "total_quantity": 84,      "variants": null    }  ],  "extra": [    "verified"  ]}

Styling and theming

The SDK exposes CSS custom properties, which you can override in your own stylesheet to align with your brand:

:root {  /* Base colors */  --pc-sdk-primary-color: #007bff;  --pc-sdk-secondary-color: #6c757d;  --pc-sdk-background-color: #ffffff;  --pc-sdk-text-color: #333333;  --pc-sdk-border-radius: 8px;  --pc-sdk-font-family: Montserrat, sans-serif;  /* Card styling */  --pc-sdk-card-background: #ffffff;  --pc-sdk-card-border: 1px solid #e9ecef;  --pc-sdk-card-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);  /* Button styling */  --pc-sdk-button-color: #007bff;  --pc-sdk-button-hover-color: #0056b3;  /* Text colors */  --pc-sdk-price-color: #28a745;  --pc-sdk-description-color: #6c757d;  /* Text alignment */  --pc-sdk-title-align: center;  --pc-sdk-description-align: center;  --pc-sdk-price-align: center;  /* Font weights and sizes */  --pc-sdk-title-font-weight: 600;  --pc-sdk-description-font-weight: 400;  --pc-sdk-price-font-weight: 700;  --pc-sdk-title-font-size: 12px;  --pc-sdk-description-font-size: 12px;  --pc-sdk-price-font-size: 12px;}

Example overrides:

.pc-sdk-product-card {  transition: transform 0.3s ease !important;}.pc-sdk-product-card:hover {  transform: translateY(-4px) !important;  box-shadow: 0 8px 16px rgba(0,0,0,0.2) !important;}.pc-sdk-product-title {  font-weight: 700 !important;  text-transform: uppercase !important;}

You can also update the theme at runtime:

sdk.updateTheme({  primaryColor: '#28a745',  backgroundColor: '#f8fff9',  borderRadius: '12px'});

Troubleshooting

Carousel not appearing

Symptoms: the container is empty and no products display.

Check:

  • The containerId in your config matches the <div id="...">.
  • The SDK script is loaded successfully in Network tab.
  • The API endpoint is correct and accessible.
  • No JavaScript errors are present in the console.

Debug example:

ProductCarousel('init', {  containerId: 'my-carousel',  apiEndpoint: 'https://api.example.com'}, function(error) {  if (error) {    console.error('Initialization error:', error);  } else {    console.log('SDK initialized successfully!');  }});

Products not loading

Symptoms: loading state persists and recommendations never render.

Check:

  • The /recommend/products endpoint returns data for the account and product_ids you are sending.
  • There are no CORS errors in the browser console.
  • The endpoint supports POST and application/json.

Test with:

curl -X POST https://api.example.com/recommend/products \  -H "Content-Type: application/json" \  -d '{"account":"your-account","product_ids":["prod1","prod2"]}'

Styling issues

If the carousel style does not match your site:

  • Use the theme object in initialization.
  • Override CSS custom properties in your stylesheet.
  • Check for CSS conflicts or overrides from your global styles.

Performance problems

If you see slow loading or lag:

  • Reduce itemsToShow on mobile.
  • Optimize product image sizes (for example, 800x800px or smaller).
  • Disable autoPlay if not needed.
  • Monitor API response time (target < 500 ms).

Browser support and performance

The Product Carousel SDK supports:

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+
  • Mobile Safari 14+
  • Chrome Mobile 90+

Typical performance characteristics:

  • Bundle size: < 100 KB (minified + gzipped)
  • Load time: < 200 ms via CDN
  • API timeout: 10 seconds with auto-retry
  • Render time: < 100 ms after data is received

API Documentation: Get Product Recommendations

This endpoint generates product recommendations based on a list of input product IDs for a specific account.

Base URL: https://infer.apps.cordial.io/

Endpoint details

Method Endpoint Content-Type
POST /recommend/products application/json

Request body parameters

The request body accepts a JSON object with the following properties:

Parameter Type Required Description
account String Yes The unique identifier for the client account (e.g., "speakercity").
product_ids Array<String> Yes An array of product IDs to use as the seed for recommendations.

Example request

JSON payload

{  "account": "speakercity",  "product_ids": [    "1",    "2"  ]}

cURL command

curl --location --request POST 'https://infer.apps.cordial.io/recommend/products' \  --header 'Content-Type: application/json' \  --data-raw '{    "account": "speakercity",    "product_ids": ["1", "2"]  }'

Response schema

The API returns a JSON object containing the list of recommended products and metadata.

Field Type Nullable Description
recommendations Array No A list of product objects recommended for the account.
product_id String No The unique identifier for the product.
score Float No The relevance score assigned by the recommendation engine (e.g., 100.0).
confidence Float No The confidence level of the recommendation (0.0 to 1.0).
category String Yes The product category (e.g., "TVs""small appliances").
gender String Yes The product gender affiliation, if applicable (e.g., "TVs"->unisex, "shirts"->male,female)
price Float Yes The current price of the product.
name String No The display name of the product.
description String Yes A brief description of the product.
url String No The direct URL to the product detail page.
image_urls Array<String> Yes An array of URLs pointing to product images.
total_quantity Integer Yes The current stock quantity available.
variants Object Yes Variant details (if applicable). Returns null if no variants exist.
extra Array<String> Yes Additional metadata tags regarding the response (e.g., ["verified"]).

Example response

{  "recommendations": [    {      "product_id": "1889075",      "score": 100.0,      "confidence": 1.0,      "category": "TVs",      "price": 713.95,      "name": "65 inch Class U6 Series Mini-LED ULED 4K Smart Google TV - 65U6N",      "description": "Hisense's 65 inch Class U6 Series Mini-LED ULED 4K Smart Google TV - 65U6N brings a perfect mix of function and style to your everyday routine.",      "url": "https://store.cordialthreads.com/collections/tvs/products/hisense-65-inch-class-u6-series-mini-led-uled-4k-smart-google-tv-65u6n",      "image_urls": [        "https://cdn.shopify.com/s/files/1/0592/9789/0510/files/28537855_fpx.jpg?v=1747713588"      ],      "total_quantity": 84,      "variants": null    },    {      "product_id": "1218850",      "score": 100.0,      "confidence": 1.0,      "category": "small appliances",      "price": 199.95,      "name": "DLC-8SBCY Pro Custom 11‚ 11 Cup Food Processor",      "description": "Cuisinart's DLC-8SBCY Pro Custom 11‚Äö√묢 11 Cup Food Processor brings a perfect mix of function and style to your everyday routine.",      "url": "https://store.cordialthreads.com/collections/small-appliances/products/cuisinart-dlc-8sbcy-pro-custom-11-11-cup-food-processor",      "image_urls": [        "https://cdn.shopify.com/s/files/1/0592/9789/0510/files/1464438_fpx.jpg?v=1747713431"      ],      "total_quantity": 47,      "variants": null    }  ],  "extra": [    "verified"  ]}


If using the API exclusively, provisioning is required for storage of anonymous product IDs and passing them in the request.
 

Comments

0 comments

Please sign in to leave a comment.