Conversion tracking
Selektable can attribute conversions to widget visualizations, so you can measure whether customers who use the widget are more likely to take action. A conversion can be a purchase, a form submission, an appointment booking, or any other goal. For WooCommerce and Shopify stores, conversion tracking is handled automatically via platform webhooks. This guide covers custom sites that need to send conversion data manually.How it works
- The embed script assigns each visitor a persistent visitor ID (stored in
localStorage) and a session ID (stored insessionStorage) - When a customer generates a visualization, it’s recorded with their visitor and session IDs
- When a conversion happens (purchase, form submission, etc.), your server sends a webhook to Selektable that includes the same IDs
- Selektable’s attribution engine matches the conversion to any recent visualizations within the attribution window (default: 7 days)
Client-side tracking
If your site doesn’t have a backend (static sites, no-code platforms, or client-rendered apps), you can track conversions directly from the browser using the embed script. No API key or server-side code needed.For sites with server access, we recommend the server-side webhook below. It’s more secure because the API key is never exposed to the browser.
Prerequisites
- The Selektable embed script must be loaded on both your product pages and your thank-you or confirmation page
- You need your store ID from the dashboard (already in the embed script tag)
Ecommerce order tracking
On your thank-you or order confirmation page, callSelektable.track() with the order details:
productId in your items should match the productId you pass to Selektable.open() on your product pages.
Lead gen / appointment tracking
For non-ecommerce conversions (form submissions, bookings), just pass anorderId:
totalCents: 0, currency: 'USD', status: 'completed', and empty items.
Property reference
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
orderId | string | Yes | — | Unique identifier for this conversion |
totalCents | integer | No | 0 | Order total in cents, or 0 for leads |
currency | string | No | 'USD' | 3-letter currency code |
status | string | No | 'completed' | One of: pending, processing, on-hold, completed, refunded, cancelled |
items | array | No | [] | Order items (see webhook reference for item fields) |
Deduplication
The SDK automatically prevents duplicate tracking when a customer refreshes the thank-you page. EachorderId is only sent once per browser session.
Prerequisites
- The Selektable embed script must be loaded on your site, including pages with forms or checkout
- You need your store ID, organization ID, and API key from the dashboard
sel_ and are used as a Bearer token in the Authorization header of every webhook request.
How tracking IDs reach your server
Selektable.getIdentity() is a client-side browser API that reads from localStorage and sessionStorage. It is not available on your server.
To send the webhook from your backend, you need to pass the tracking IDs from the browser through your form using hidden fields. Add these to any form where you want to track conversions:
visitorId and sessionId from the form submission and includes them in the webhook payload.
Ecommerce order tracking
Track purchases by sending the order details along with the visitor’s tracking IDs from your server. Step 1: Add hidden tracking fields to your checkout form (see above). Step 2: When the order is placed, send the webhook from your server.Lead gen / appointment tracking
If your site uses a contact form, appointment booking, or any non-ecommerce conversion, you can track form submissions as conversions. SettotalCents to 0 and pass an empty items array.
Step 1: Add hidden tracking fields to your form.
Webhook payload reference
| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | Unique identifier for this conversion (order ID, form submission ID, etc.) |
storeId | string | Yes | Your Selektable store ID |
organizationId | string | Yes | Your Selektable organization ID |
visitorId | string | Yes | From Selektable.getIdentity().visitorId on the client, passed to your server via hidden form fields |
sessionId | string | Yes | From Selektable.getIdentity().sessionId on the client, passed to your server via hidden form fields |
totalCents | integer | Yes | Order total in cents, or 0 for lead gen |
currency | string | Yes | 3-letter currency code (e.g., USD, EUR) |
platform | string | Yes | Must be "custom" |
status | string | Yes | One of: pending, processing, on-hold, completed, refunded, cancelled |
orderCreatedAt | string | Yes | ISO 8601 date string |
items | array | Yes | Array of order items, or [] for lead gen |
| Field | Type | Required | Description |
|---|---|---|---|
productId | string | Yes | Must match the productId passed to Selektable.open() |
quantity | integer | Yes | Quantity purchased |
priceCents | integer | Yes | Unit price in cents |
totalCents | integer | Yes | Line total in cents (priceCents * quantity) |
Viewing conversion data
Once conversions are tracked, analytics appear in your dashboard:- Go to the Selektable dashboard
- Open your store and select a widget
- Navigate to the Analytics tab
- Recent conversions with IDs and attributed revenue (or $0 for leads)
- Conversion type (direct or assisted)
- Time to conversion showing how long after a visualization the action occurred
Troubleshooting
Webhook returns 401 Unauthorized
Webhook returns 401 Unauthorized
Conversions aren't showing in the dashboard
Conversions aren't showing in the dashboard
Verify that:
- The
Authorizationheader includes a valid API key. - The
visitorIdandsessionIdare not empty. LogSelektable.getIdentity()on the client to check the values before form submission. - The
storeIdandorganizationIdmatch your dashboard values. - The webhook returns
{ "success": true }.
Visitor ID is different on the thank you page
Visitor ID is different on the thank you page
The visitor ID is stored in
localStorage on the same domain. If your form redirects to a different domain (e.g., a third-party payment page or booking tool), the visitor ID won’t carry over. Make sure the form page is on the same domain as your product pages.Session ID is empty after redirect
Session ID is empty after redirect
The session ID uses
sessionStorage, which resets when a new tab opens. If your checkout or form flow opens a new tab or window, the session ID will be different. The visitor ID (which persists across sessions) is more reliable for attribution in these cases.Next steps
Identity tracking
Associate visualizations with logged-in customer accounts
Custom store setup
Full guide to integrating the widget on a custom site