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:
- You install the Product Carousel SDK on your website.
- You place a container element where you want recommendations to appear.
- 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). - 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-color,data-background-color,data-text-color,data-border-radius, anddata-font-family.
JavaScript-only configuration
Some options are only available in JavaScript (not via data attributes), including:
- Display options:
showPrice,showDescription,maxDescriptionLength,imageAspectRatio - Typography alignment and font weights/sizes
- Advanced theme controls:
cardBackground,cardBorder,cardShadow,buttonColor,priceColor - Callbacks:
onProductClick - Responsive configuration
- Event configuration:
eventTypes,eventNames - Custom text messages:
loadingText,errorText,noProductsText
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
eventTypesandeventNames(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 URL: https://infer.apps.cordial.io
Endpoint: POST /recommend/products
Content-Type: application/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
containerIdin 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/productsendpoint returns data for theaccountandproduct_idsyou 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
themeobject 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
itemsToShowon mobile. - Optimize product image sizes (for example, 800x800px or smaller).
- Disable
autoPlayif 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.