Custom Storefront & Device Fingerprinting Setup
Updated on 22.06.26
1 minute to read
Copy link
Overview
The SEON browser agent gathers device intelligence and produces a session payload that is attached to orders for fraud analysis. This enables device fingerprinting — a critical component of SEON's fraud detection.
Theme storefronts (Online Store 2.0 / Liquid)
The SEON app includes a theme extension that handles device fingerprinting automatically on every page — no coding required. You just need to enable it in the Theme Editor.
How to enable:
- Go to Online Store - Themes in your Shopify admin.
- Click Customize on your active theme.
- In the Theme Editor, navigate to App embeds (in the left sidebar).
- Find SEON Script and toggle it on.
- Click Save.
Once enabled, device fingerprinting runs automatically on every storefront page. No blocks to add, no code to write.
Custom / headless storefronts (Hydrogen, Next.js, Remix, Nuxt, etc.)
For custom storefronts where the theme extension is not supported, you must manually embed the SEON agent script. It handles fingerprint generation, cart token tracking, and session payload creation.
Integration guide for custom storefronts
Add the following script to your storefront's root layout (e.g. app.tsx, index.html, or root layout component). It initializes automatically once the DOM is ready.
(function () {
'use strict';
if (window.SEON_AGENT) return;
const STORAGE_KEYS = {
VISITOR_ID: 'seon_visitor_id',
CART_TOKEN: 'seon_cart_token',
};
const defaultConfig = {
cartEndpoint: '/cart.json',
autoInit: true,
dnsResolverDomain: 'seonintelligenceresolver.com',
fieldTimeoutMs: 2000,
networkTimeoutMs: 2000,
region: 'eu',
silentMode: true,
};
const config = { ...defaultConfig, ...(window.SEON_CONFIG || {}) };
let isInitialized = false;
let initializationPromise = null;
let isSdkLoaded = false;
function loadSeonSdk() {
return new Promise((resolve, reject) => {
if (isSdkLoaded) { resolve(); return; }
const script = document.createElement('script');
script.src = 'https://cdn.seonintelligence.com/js/v6/agent.umd.js';
script.fetchPriority = 'low';
script.defer = true;
script.onload = () => {
isSdkLoaded = true;
if (window.seon && typeof window.seon.init === 'function') {
window.seon.init();
}
resolve();
};
script.onerror = () => reject(new Error('Failed to load SEON SDK'));
document.head.appendChild(script);
});
}
async function generateSession(token) {
const sdk = window.seon;
if (!sdk || typeof sdk.getSession !== 'function') return;
try {
const data = await sdk.getSession({
dnsResolverDomain: config.dnsResolverDomain,
fieldTimeoutMs: config.fieldTimeoutMs,
networkTimeoutMs: config.networkTimeoutMs,
region: config.region,
silentMode: config.silentMode,
geolocation: { canPrompt: false },
});
if (typeof data === 'string' && data.trim().length > 0) {
localStorage.setItem(STORAGE_KEYS.VISITOR_ID, data);
}
} catch {
// Silently fail
}
}
async function checkAndUpdateSession(initialToken = null) {
let token = initialToken || crypto.randomUUID();
let gotCart = false;
try {
const response = await fetch(config.cartEndpoint, { priority: 'low' });
const cart = await response.json();
token = cart.token;
gotCart = true;
} catch {
// Use initial token
}
const storedToken = localStorage.getItem(STORAGE_KEYS.CART_TOKEN);
const tokenChanged = gotCart && storedToken !== token;
const hasVisitorId = localStorage.getItem(STORAGE_KEYS.VISITOR_ID);
if (tokenChanged) {
localStorage.setItem(STORAGE_KEYS.CART_TOKEN, token);
localStorage.removeItem(STORAGE_KEYS.VISITOR_ID);
}
if (tokenChanged || !hasVisitorId) {
await generateSession(token);
}
}
async function initialize() {
if (isInitialized) return;
if (initializationPromise) return initializationPromise;
initializationPromise = (async () => {
await loadSeonSdk();
await new Promise(resolve => setTimeout(resolve, 1000));
await checkAndUpdateSession();
isInitialized = true;
})();
return initializationPromise;
}
window.SEON_AGENT = {
init: initialize,
getVisitorId: () => localStorage.getItem(STORAGE_KEYS.VISITOR_ID),
getCartToken: () => localStorage.getItem(STORAGE_KEYS.CART_TOKEN),
updateSession: async (token) => {
if (!isInitialized) throw new Error('SEON not initialized. Call init() first.');
await checkAndUpdateSession(token);
},
clearSession: () => {
localStorage.removeItem(STORAGE_KEYS.VISITOR_ID);
localStorage.removeItem(STORAGE_KEYS.CART_TOKEN);
},
isInitialized: () => isInitialized,
getConfig: () => ({ ...config }),
};
if (config.autoInit) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initialize);
} else {
initialize();
}
}
})();Configuration options
Customize agent behavior by setting window.SEON_CONFIG before the script loads:
window.SEON_CONFIG = {
cartEndpoint: '/cart.json', // Shopify cart endpoint — adjust for custom setups
autoInit: true, // Auto-initialize on DOM ready
dnsResolverDomain: 'seonintelligenceresolver.com', // SEON collection domain
fieldTimeoutMs: 2000, // Timeout per fingerprinting field (ms)
networkTimeoutMs: 2000, // Network request timeout (ms)
region: 'eu', // SEON region ('eu', 'us')
silentMode: true, // Suppress SDK console output
};How it works
The device fingerprinting system has two parts:
Storefront script (theme extension or manual agent)
- Loads the SEON SDK and initializes on every page
- Fetches the current Shopify cart token from
/cart.json(or generates a random UUID if unavailable) - Generates a device fingerprint session payload
- Stores the payload in localStorage under
seon_visitor_id, keyed to the cart token
Web pixel (automatic)
- A Shopify web pixel extension runs automatically at checkout
- On the
checkout_completedevent, it reads the fingerprint from localStorage - Sends the payload to the SEON app's backend, where it is associated with the order for fraud analysis
The storefront script collects, the web pixel delivers. Both parts must be working for device fingerprinting data to appear in the fraud analysis.
Public API
Once initialized, window.SEON_AGENT exposes these methods:
init()— Manually initialize the agent (ifautoInitis disabled)getVisitorId()— Returns the current session payloadgetCartToken()— Returns the current Shopify cart tokenupdateSession(token)— Force update the session with a new tokenclearSession()— Clears stored visitor ID and cart tokenisInitialized()— Returnstrueif the agent has been initializedgetConfig()— Returns the current configuration object
Troubleshooting
- Fingerprint not generated — Script not loaded before checkout. Ensure the script is in the root layout and loads on every page.
- Cart token issues — Custom storefront doesn't use
/cart.json. UpdatecartEndpointin the config to match your setup. - Multiple initializations — Script included more than once. The script guards against this — if
window.SEON_AGENTalready exists, it won't reinitialize. - CSP errors — Content Security Policy blocking the SDK. Allow
cdn.seonintelligence.comin yourscript-srcdirective. - Fingerprint missing on theme storefront — Theme extension not enabled. Go to Online Store – Themes – Customize – App embeds and toggle on SEON Script.