# How can we help?

## 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:

```html
<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:

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

Step 3: Initialize and load recommendations.

```html
<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.

```html
<!-- 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:

```html
<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:

```html
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:

```html
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

```html
<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

```html
<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

```html
<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

```html
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.

```html
<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`, and `data-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:

```html
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:

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

Broadcasting events from elsewhere in your application:

```html
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`](https://infer.apps.cordial.io/)

Endpoint: `POST /recommend/products`

Content-Type: `application/json`

### Request body

```json
{  "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:

```bash
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:

```json
{  "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:

```css
: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:

```css
.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:

```html
<script>sdk.updateTheme({  primaryColor: '#28a745',  backgroundColor: '#f8fff9',  borderRadius: '12px'});
</script>
```

## 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:

```html
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:

```bash
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).
