Skip to content

JavaScript API

Once loaded, the script exposes a global window.ZoriHQ object for custom tracking.

window.ZoriHQ.track('button_clicked', {
button_name: 'Sign Up',
page: 'homepage'
});
window.ZoriHQ.push(['track', 'purchase_completed', {
product_id: 'prod_123',
amount: 99.99
}]);

The queue method is especially useful when you need to track events immediately on page load, before the script has finished loading.

Link visitor cookies to your application users. This is crucial for revenue attribution.

window.ZoriHQ.identify({
app_id: 'user_123', // Your app's user ID (required)
email: '[email protected]', // User email
fullname: 'John Doe', // Full name
plan: 'premium', // Custom properties
signup_date: '2025-01-15'
});
window.ZoriHQ.push(['identify', {
app_id: 'user_123',
fullname: 'John Doe'
}]);

The visitor ID is essential for revenue attribution. Pass it to Stripe when creating checkouts.

const visitorId = await window.ZoriHQ.getVisitorId();
console.log('Visitor ID:', visitorId);
window.ZoriHQ.push(['getVisitorId', function(id) {
console.log('Visitor ID:', id);
}]);
const sessionId = window.ZoriHQ.getSessionId();

Sessions automatically restart after:

  • 30 minutes of inactivity
  • Different UTM parameters (new campaign)
  • Browser session ends
window.ZoriHQ.setConsent({
analytics: true, // Allow analytics tracking
marketing: false // Deny marketing tracking
});
const hasConsent = window.ZoriHQ.hasConsent();
if (hasConsent) {
// User has given consent
}

For GDPR right to be forgotten:

window.ZoriHQ.optOut();

This deletes all cookies and localStorage data and blocks future tracking.

// Set consent before script loads
window.ZoriHQ.push(['setConsent', { analytics: true }]);
// Or opt out
window.ZoriHQ.push(['optOut']);

Here’s a typical implementation:

<!-- Initialize queue -->
<script>
window.ZoriHQ = window.ZoriHQ || [];
</script>
<!-- Load script -->
<script async src="https://cdn.zorihq.com/script.min.js"
data-key="your-publishable-key"></script>
<script>
// Track page view immediately
window.ZoriHQ.push(['track', 'page_view']);
// When user logs in
function onUserLogin(user) {
window.ZoriHQ.push(['identify', {
app_id: user.id,
email: user.email,
fullname: user.name
}]);
}
// When starting checkout
async function startCheckout(cartItems) {
const visitorId = await window.ZoriHQ.getVisitorId();
// Send to your backend
const response = await fetch('/api/create-checkout', {
method: 'POST',
body: JSON.stringify({
items: cartItems,
zori_visitor_id: visitorId // Critical for attribution!
})
});
const { checkoutUrl } = await response.json();
window.location.href = checkoutUrl;
}
// Track custom events
document.querySelector('.signup-btn').addEventListener('click', () => {
window.ZoriHQ.push(['track', 'signup_clicked', {
location: 'hero_section'
}]);
});
</script>

If you’re using TypeScript, you can add type definitions:

interface ZoriHQ {
track(eventName: string, properties?: Record<string, any>): Promise<void>;
identify(userInfo: {
app_id: string;
email?: string;
fullname?: string;
[key: string]: any;
}): Promise<void>;
getVisitorId(): Promise<string>;
getSessionId(): string;
setConsent(preferences: { analytics?: boolean; marketing?: boolean }): void;
hasConsent(): boolean;
optOut(): void;
push(args: any[]): void;
}
declare global {
interface Window {
ZoriHQ: ZoriHQ | any[];
}
}