Skip to main content
The Upstack JavaScript SDK provides client-side event tracking, user identification, and session management. It captures browsing behavior, resolves user identity across devices, and forwards events to your configured destinations.
Important: The correct global is window._upstack() (with underscore), not window.upstack(). Older documentation may reference the incorrect name.

Installation

The Upstack pixel is distributed via CDN, not npm. Add this snippet to your site’s <head>:
<script>
window._upstack = window._upstack || function() {
  (window._upsqueue = window._upsqueue || []).push(arguments);
};
_upstack('init', 'YOUR_PIXEL_ID');
</script>
<script async src="https://prod2-cdn.upstackified.com/scripts/px/ups.min.js"></script>
Why this works:
  1. The inline script defines _upstack() as a function that pushes calls to a queue
  2. Calls made before the SDK loads are queued — no events are lost
  3. Once the SDK loads, it processes the queue and replaces _upstack() with the real implementation
  4. Safe to call immediately without checking load status

API Overview

MethodVia QueueVia Direct ClientDescription
init✅ (pixelId only)Initialize the pixel
pageTrack page views
trackTrack custom events
identifyAssociate user identity
metricSend metrics (currently disabled)
resetClear identity state
isKnownCheck if user is identified
getUpstackIdGet Upstack ID object

Queue Commands

These methods can be called via _upstack('command', ...) before or after the SDK loads.

init(pixelId)

Initialize the Upstack pixel with your pixel ID.
function init(
  pixelId: string,
  identityTraits?: EventIdentityTraits,
  scriptSource?: 'js' | 'shopify_js' | 'shopify_ext'
): Promise<{ isInitialized: boolean; isDisabled: boolean }>
Parameters:
ParameterTypeRequiredDescription
pixelIdstringYesYour Upstack pixel ID from the dashboard (starts with px_)
identityTraitsEventIdentityTraitsNoPre-populate identity on init
scriptSourcestringNoScript origin: 'js' (default), 'shopify_js', 'shopify_ext'
Queue Limitation: When using _upstack('init', pixelId, identityTraits, scriptSource), only pixelId is passed to the init function. The identityTraits and scriptSource parameters are dropped by the queue processor.For full init with identity traits, use the direct client after the script loads.
Examples:
// Basic initialization via queue (recommended)
_upstack('init', 'px_abc123def456');

// Full init with identity traits (requires direct client)
// Wait for script to load first
if (window._upsClient) {
  await window._upsClient.init('px_abc123def456', {
    emails: ['user@example.com']
  }, 'js');
}

page(eventData?)

Track a page view. Automatically captures page URL, title, referrer, and path.
function page(eventData?: Record<string, unknown>): void
Parameters:
ParameterTypeRequiredDescription
eventDataobjectNoCustom properties to include with the page view
Auto-captured properties:
  • page_url — Current page URL
  • page_title — Document title
  • page_referrer — Referring URL
  • page_path — URL path
Examples:
// Basic page view
_upstack('page');

// With custom properties
_upstack('page', {
  page_category: 'product',
  product_id: 'SKU123',
  collection: 'summer-2026'
});

track(eventName, eventData?, …)

Track a custom event. Supports 7 positional parameters plus a shorthand for useBeacon.
function track(
  eventName: string,
  eventData?: Record<string, unknown>,
  eventId?: string,
  contextOverride?: Record<string, unknown>,
  collectedAt?: string,        // ISO 8601 timestamp
  collectedAtEpoch?: number,   // Unix epoch milliseconds
  options?: TrackOptions
): void

interface TrackOptions {
  useBeacon?: boolean;  // Use navigator.sendBeacon() for page unload
}
Parameters:
ParameterTypeRequiredDescription
eventNamestringYesEvent name in snake_case (e.g., 'add_to_cart', 'purchase')
eventDataobjectNoEvent properties
eventIdstringNoUnique ID for deduplication across destinations
contextOverrideobjectNoOverride page/session context for this event
collectedAtstringNoISO 8601 timestamp for backdated events
collectedAtEpochnumberNoUnix epoch milliseconds for backdated events
optionsTrackOptionsNo{ useBeacon: boolean } for page unload tracking
Shorthand for useBeacon: When the 4th argument is an object with useBeacon, it’s treated as options:
// Shorthand (recommended for useBeacon)
_upstack('track', 'lead', { email: 'user@example.com' }, { useBeacon: true });

// Full positional form (7 parameters)
_upstack('track', 'lead', { email: 'user@example.com' }, null, null, null, null, { useBeacon: true });
Examples:
// Basic tracking
_upstack('track', 'add_to_cart', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99, quantity: 1 }],
  value: 29.99,
  currency: 'USD'
});

// With deduplication ID (prevents duplicate events at destinations)
_upstack('track', 'purchase', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99, quantity: 1 }],
  value: 29.99,
  order_id: 'ORD-456',
  currency: 'USD'
}, 'ORD-456');

// Backdated event (server-side timestamp)
_upstack('track', 'server_event', {
  value: 50
}, null, null, '2026-06-01T12:00:00Z');

// Page unload with beacon (using shorthand)
window.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    _upstack('track', 'page_exit', {
      time_on_page_seconds: Math.round((Date.now() - pageLoadTime) / 1000)
    }, { useBeacon: true });
  }
});

identify(userId?, data?)

Associate user identity with the current session. Used for cross-device tracking and destination matching.
function identify(
  userId?: string | null,
  data?: EventIdentityTraits
): void

interface EventIdentityTraits {
  emails?: string[];      // Array of email addresses
  phones?: string[];      // Array of phone numbers (E.164 format preferred)
  firstName?: string;
  lastName?: string;
  address?: {
    city?: string;
    state?: string;
    zip?: string;
    country?: string;
  };
}
Parameters:
ParameterTypeRequiredDescription
userIdstring | nullNoYour internal user ID. Pass null for anonymous identification with traits only.
dataEventIdentityTraitsNoIdentity traits with emails[] and phones[] as arrays
Important: emails and phones are arrays, not single values. This supports users with multiple contact methods.
Examples:
// With userId only
_upstack('identify', 'user-456');

// With full profile
_upstack('identify', 'user-456', {
  emails: ['jane@example.com', 'jane.doe@work.com'],
  phones: ['+15551234567'],
  firstName: 'Jane',
  lastName: 'Doe',
  address: {
    city: 'Austin',
    state: 'TX',
    zip: '78701',
    country: 'US'
  }
});

// Traits only (Shopify path — userId is null)
_upstack('identify', null, {
  emails: ['customer@example.com']
});

// After form submission
document.querySelector('form').addEventListener('submit', (e) => {
  const email = e.target.querySelector('[name="email"]').value;
  _upstack('identify', null, { emails: [email] });
});

metric(metricName, metricValue, metricData?, metricId?)

Send a custom metric value.
function metric(
  metricName: string,
  metricValue: number,
  metricData?: Record<string, unknown>,
  metricId?: string
): null
Currently Disabled: The metric() method is routed through the queue but returns null — metric forwarding is disabled in the public SDK. This method exists for future use.
Parameters:
ParameterTypeRequiredDescription
metricNamestringYesMetric name
metricValuenumberYesNumeric value
metricDataobjectNoAdditional context
metricIdstringNoUnique ID for deduplication
Example:
// Currently returns null — metric forwarding disabled
_upstack('metric', 'page_load_time', 1250, {
  page: '/checkout'
});

reset()

Clear identity, session data, event listeners, and hooks. Call when a user logs out.
function reset(): void
Example:
function handleLogout() {
  _upstack('reset');
  window.location.href = '/login';
}

Direct Client Methods

These methods are only available via window._upsClient after initialization completes. They cannot be called through the _upstack() queue.

isKnown()

Check if the current user has been identified.
function isKnown(): Promise<boolean>
Returns: Promise resolving to true if the user has been identified, false otherwise.
Direct Client Only: This method is NOT available via the _upstack() queue. You must call it directly on window._upsClient.
Example:
// After init completes
const isKnown = await window._upsClient.isKnown();
if (!isKnown) {
  showEmailCapturePopup();
}

getUpstackId()

Retrieve the Upstack identity object for the current user.
interface UpstackId {
  _upstackId?: string;   // Persistent user ID
  _upstackSid?: string;  // Session ID
  _upstackIp?: string;   // IP address (if available)
}

function getUpstackId(): Promise<UpstackId>
Returns: Promise resolving to an UpstackId object (not a string).
Direct Client Only: This method is NOT available via the _upstack() queue. You must call it directly on window._upsClient.Return Type: Returns an object with identity fields, not a single string ID.
Example:
// After init completes
const upstackId = await window._upsClient.getUpstackId();
console.log('Upstack ID:', upstackId._upstackId);
console.log('Session ID:', upstackId._upstackSid);

// Use for server-side API calls
fetch('/api/track', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    upstack_id: upstackId._upstackId,
    event: 'server_purchase',
    value: 99.99
  })
});

Waiting for SDK Ready

When using direct client methods, ensure the SDK has loaded:
function onUpstackReady(callback) {
  if (window._upsClient && window._upsClient._initialized) {
    callback();
  } else {
    const interval = setInterval(() => {
      if (window._upsClient && window._upsClient._initialized) {
        clearInterval(interval);
        callback();
      }
    }, 100);
  }
}

// Usage
onUpstackReady(async () => {
  const isKnown = await window._upsClient.isKnown();
  if (isKnown) {
    const upstackId = await window._upsClient.getUpstackId();
    console.log('User ID:', upstackId._upstackId);
  }
});

Common Patterns

SPA Navigation Tracking

Track page views on route changes in single-page applications:
// React Router
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function usePageTracking() {
  const location = useLocation();
  
  useEffect(() => {
    _upstack('page', {
      page_path: location.pathname,
      page_search: location.search
    });
  }, [location]);
}

// Next.js App Router
'use client';
import { usePathname, useSearchParams } from 'next/navigation';
import { useEffect } from 'react';

export function Analytics() {
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() => {
    _upstack('page', {
      page_path: pathname,
      page_search: searchParams.toString()
    });
  }, [pathname, searchParams]);

  return null;
}

E-commerce Funnel

Track the complete customer journey:
// Product view
_upstack('track', 'view_content', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99 }]
});

// Add to cart
_upstack('track', 'add_to_cart', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99, quantity: 1 }],
  value: 29.99,
  currency: 'USD'
});

// Begin checkout
_upstack('track', 'initiate_checkout', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99, quantity: 1 }],
  value: 29.99,
  currency: 'USD'
});

// Purchase (with deduplication ID)
_upstack('track', 'purchase', {
  items: [{ id: 'SKU123', name: 'Widget', price: 29.99, quantity: 1 }],
  value: 29.99,
  order_id: 'ORD-456',
  currency: 'USD'
}, 'ORD-456');

Page Exit Tracking with Beacon

Reliably track time on page even when the user closes the tab:
let pageLoadTime = Date.now();

window.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    const timeOnPage = Math.round((Date.now() - pageLoadTime) / 1000);
    _upstack('track', 'page_exit', {
      time_on_page_seconds: timeOnPage,
      page_path: window.location.pathname
    }, { useBeacon: true });
  }
});

Form Submission Tracking

Capture leads from newsletter signups:
document.querySelector('#newsletter-form').addEventListener('submit', (e) => {
  e.preventDefault();
  const email = e.target.querySelector('[name="email"]').value;
  
  // Identify the user
  _upstack('identify', null, { emails: [email] });
  
  // Track the lead event with beacon (in case form navigates away)
  _upstack('track', 'lead', {
    source: 'newsletter_signup',
    email: email
  }, { useBeacon: true });
  
  // Submit the form
  e.target.submit();
});

TypeScript Support

Add type declarations for TypeScript projects:
declare global {
  interface Window {
    _upstack: (...args: unknown[]) => void;
    _upsqueue: unknown[];
    _upsClient: {
      init: (pixelId: string, identityTraits?: EventIdentityTraits, scriptSource?: string) => Promise<{ isInitialized: boolean; isDisabled: boolean }>;
      page: (eventData?: Record<string, unknown>) => void;
      track: (eventName: string, eventData?: Record<string, unknown>, eventId?: string, contextOverride?: Record<string, unknown>, collectedAt?: string, collectedAtEpoch?: number, options?: TrackOptions) => void;
      identify: (userId?: string | null, data?: EventIdentityTraits) => void;
      metric: (metricName: string, metricValue: number, metricData?: Record<string, unknown>, metricId?: string) => null;
      reset: () => void;
      isKnown: () => Promise<boolean>;
      getUpstackId: () => Promise<UpstackId>;
      _initialized: boolean;
    };
  }
}

interface EventIdentityTraits {
  emails?: string[];
  phones?: string[];
  firstName?: string;
  lastName?: string;
  address?: {
    city?: string;
    state?: string;
    zip?: string;
    country?: string;
  };
}

interface TrackOptions {
  useBeacon?: boolean;
}

interface UpstackId {
  _upstackId?: string;
  _upstackSid?: string;
  _upstackIp?: string;
}

export {};

Methods NOT Available

The following methods are not implemented in the public SDK:
  • consent — Not implemented
  • group — Not implemented (stub exists)
  • screen — Not implemented (stub exists)
  • alias — Not implemented (stub exists)
Internal methods (do not call directly):
  • notify — Internal hook messaging
  • postInit — Internal post-initialization

Pixel Setup

Installation guide for non-Shopify websites and SPAs.

Standard Events

Complete reference for all standard events with JavaScript snippets.

Properties & Context

Reference for item arrays, customer data, and auto-captured fields.

Custom Events

Create events beyond the standard taxonomy for your needs.

Identity Resolution

How identify() connects sessions to customer profiles.

Shopify Automatic Tracking

Events tracked automatically on Shopify stores.