@converlay/sdk
v1.0.0
Published
Converlay event tracking SDK for Hydrogen and headless storefronts
Downloads
64
Maintainers
Readme
@converlay/sdk
Lightweight event tracking SDK for any JavaScript storefront — Shopify Hydrogen, Next.js, Remix, Nuxt, or plain HTML. Sends events to the Converlay server-side collector for routing to GA4, Meta CAPI, and TikTok Events API.
Zero dependencies. ~2 KB gzipped. TypeScript-first.
Install
npm install @converlay/sdkQuick start
Vanilla JavaScript
import { createConverlay } from '@converlay/sdk';
const converlay = createConverlay({
shopDomain: 'your-store.myshopify.com',
});
converlay.identify({
email: '[email protected]',
firstName: 'Jane',
});
converlay.track('page_view');
converlay.track('purchase', {
ecommerce: {
transaction_id: 'ORD-1234',
value: 79.99,
currency: 'USD',
items: [
{ item_id: 'SKU-001', item_name: 'Classic Tee', price: 39.99, quantity: 2 },
],
},
});React (Next.js, Hydrogen, Remix)
Works with any React framework. The @converlay/sdk/react entry point provides a context provider and hook.
import { ConverlayProvider, useConverlay } from '@converlay/sdk/react';
// In your app layout (e.g. _app.tsx, layout.tsx, root.tsx)
function App() {
return (
<ConverlayProvider shopDomain="your-store.myshopify.com" autoPageView>
<Shop />
</ConverlayProvider>
);
}
// In any component
function ProductPage({ product }) {
const converlay = useConverlay();
const handleAddToCart = () => {
converlay.track('add_to_cart', {
ecommerce: {
value: product.price,
currency: 'USD',
items: [{ item_id: product.sku, item_name: product.title, price: product.price, quantity: 1 }],
},
});
};
return <button onClick={handleAddToCart}>Add to cart</button>;
}API reference
createConverlay(config)
Creates a tracking instance. Returns a ConverlayInstance.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| shopDomain | string | — | Required. Your *.myshopify.com domain. |
| endpoint | string | https://converlay.app/api/events/collect | Collector endpoint URL. |
| autoPageView | boolean | false | Automatically send a page_view event on init. |
| debug | boolean | false | Log events and transport details to the console. |
| consent | ConsentInput | { analytics: true, marketing: true } | Initial consent state. |
Instance methods
track(eventName, properties?)
Send a tracking event. Non-blocking — events are queued and sent asynchronously.
converlay.track('view_item', {
pageType: 'product',
ecommerce: {
items: [{ item_id: 'SKU-42', item_name: 'Hoodie', price: 59.99, quantity: 1 }],
},
});TrackProperties fields:
| Field | Type | Description |
|-------|------|-------------|
| ecommerce | EcommerceData | Ecommerce event data (items, value, currency, etc.). |
| userData | UserData | Per-event user data (merged with identify data). |
| pageType | string | Page type identifier (e.g. "product", "collection"). |
| [key: string] | unknown | Any additional custom properties. |
identify(data)
Set persistent user identity. Data is included in all subsequent events.
converlay.identify({
customerId: 'cust_123',
email: '[email protected]',
phone: '+15551234567',
firstName: 'Jane',
lastName: 'Doe',
});IdentifyData fields: customerId, email, phone, firstName, lastName, city, state, country, postalCode.
setConsent(consent)
Update consent state. Partial updates are supported — omitted fields keep their current value.
converlay.setConsent({ analytics: true, marketing: false });flush()
Returns a Promise<void> that resolves when all queued events have been sent.
await converlay.flush();destroy()
Tears down the instance. All subsequent track() calls become no-ops.
converlay.destroy();React API
<ConverlayProvider>
Wraps your app and creates a single tracking instance. Accepts the same props as createConverlay config, plus children.
<ConverlayProvider
shopDomain="your-store.myshopify.com"
autoPageView
debug={false}
consent={{ analytics: true, marketing: true }}
>
{children}
</ConverlayProvider>The instance is destroyed automatically on unmount and recreated if config props change.
Next.js App Router:
ConverlayProvideruses browser APIs (localStorage,sendBeacon), so it must run on the client. Add'use client'to the file that renders the provider, or wrap it in a client component.
useConverlay()
Returns the ConverlayInstance from context. Must be called inside a <ConverlayProvider>.
const converlay = useConverlay();
converlay.track('custom_event');Ecommerce tracking
Standard ecommerce events follow GA4 naming conventions.
// Purchase
converlay.track('purchase', {
ecommerce: {
transaction_id: 'ORD-5678',
value: 149.97,
currency: 'USD',
items: [
{ item_id: 'SKU-A', item_name: 'Sneakers', price: 99.99, quantity: 1 },
{ item_id: 'SKU-B', item_name: 'Socks', price: 24.99, quantity: 2 },
],
},
});
// Add to cart
converlay.track('add_to_cart', {
ecommerce: {
value: 49.99,
currency: 'USD',
items: [{ item_id: 'SKU-C', item_name: 'Cap', price: 49.99, quantity: 1 }],
},
});
// View item list
converlay.track('view_item_list', {
ecommerce: {
item_list_id: 'best-sellers',
item_list_name: 'Best Sellers',
items: [
{ item_id: 'SKU-1', item_name: 'Product A', price: 29.99, quantity: 1 },
{ item_id: 'SKU-2', item_name: 'Product B', price: 39.99, quantity: 1 },
],
},
});EcommerceData fields: transaction_id, value, currency, items, item_list_id, item_list_name, search_term.
EcommerceItem fields: item_id (required), item_name, item_variant, price (required), quantity (required).
Consent
The SDK maps a simple { analytics, marketing } input to Google Consent Mode v2 signals:
| Input | GCM v2 signals |
|-------|----------------|
| analytics: true | analytics_storage: "granted" |
| marketing: true | ad_storage: "granted", ad_user_data: "granted", ad_personalization: "granted" |
Default consent is { analytics: true, marketing: true }. Update it at any time:
converlay.setConsent({ marketing: false });
// analytics remains true, marketing-related signals become "denied"Shopify Customer Privacy API
For Shopify storefronts using the native cookie banner, map Shopify's consent flags:
const customerPrivacy = window.Shopify?.customerPrivacy;
converlay.setConsent({
analytics: customerPrivacy?.analyticsProcessingAllowed() ?? true,
marketing: customerPrivacy?.marketingAllowed() ?? true,
});How it works
- Persistent IDs — A
client_id(UUID v4) persists inlocalStorageacross sessions. Asession_idresets after 30 minutes of inactivity (GA4 default). Falls back to in-memory storage whenlocalStorageis unavailable. - Auto-captured params — UTM parameters (
utm_source,utm_medium,utm_campaign,utm_term,utm_content) and click IDs (gclid,fbclid,ttclid) are extracted from the current URL and included in every event. - Facebook IDs —
fbp(browser ID) is generated and persisted.fbcis derived fromfbclidwhen present. - Transport — Events are sent via
navigator.sendBeacon(survives page unload). Falls back tofetchwithkeepalive: true. - Privacy — PII is hashed server-side, not in the SDK. Raw data leaves the browser over HTTPS and is hashed before forwarding to destinations.
TypeScript
All types are exported from the main entry point:
import type {
ConverlayConfig,
ConverlayInstance,
TrackProperties,
IdentifyData,
ConsentInput,
EcommerceData,
EcommerceItem,
EventPayload,
UserData,
ConsentData,
} from '@converlay/sdk';License
MIT
