> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upstackdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upstack Data JavaScript SDK Reference

> Complete API reference for the Upstack Data JavaScript SDK. Covers all 6 queue commands, 2 direct client methods, TypeScript support, and usage patterns.

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.

<Warning>
  **Important:** The correct global is `window._upstack()` (with underscore), not `window.upstack()`. Older documentation may reference the incorrect name.
</Warning>

## Installation

The Upstack pixel is distributed via CDN, not npm. Add this snippet to your site's `<head>`:

```html theme={null}
<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

| Method         | Via Queue        | Via Direct Client | Description                       |
| -------------- | ---------------- | ----------------- | --------------------------------- |
| `init`         | ✅ (pixelId only) | ✅                 | Initialize the pixel              |
| `page`         | ✅                | ✅                 | Track page views                  |
| `track`        | ✅                | ✅                 | Track custom events               |
| `identify`     | ✅                | ✅                 | Associate user identity           |
| `metric`       | ✅                | ✅                 | Send metrics (currently disabled) |
| `reset`        | ✅                | ✅                 | Clear identity state              |
| `isKnown`      | ❌                | ✅                 | Check if user is identified       |
| `getUpstackId` | ❌                | ✅                 | Get 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.

```typescript theme={null}
function init(
  pixelId: string,
  identityTraits?: EventIdentityTraits,
  scriptSource?: 'js' | 'shopify_js' | 'shopify_ext'
): Promise<{ isInitialized: boolean; isDisabled: boolean }>
```

**Parameters:**

| Parameter        | Type                  | Required | Description                                                      |
| ---------------- | --------------------- | -------- | ---------------------------------------------------------------- |
| `pixelId`        | `string`              | Yes      | Your Upstack pixel ID from the dashboard (starts with `px_`)     |
| `identityTraits` | `EventIdentityTraits` | No       | Pre-populate identity on init                                    |
| `scriptSource`   | `string`              | No       | Script origin: `'js'` (default), `'shopify_js'`, `'shopify_ext'` |

<Warning>
  **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.
</Warning>

**Examples:**

```javascript theme={null}
// 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.

```typescript theme={null}
function page(eventData?: Record<string, unknown>): void
```

**Parameters:**

| Parameter   | Type     | Required | Description                                     |
| ----------- | -------- | -------- | ----------------------------------------------- |
| `eventData` | `object` | No       | Custom 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:**

```javascript theme={null}
// 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`.

```typescript theme={null}
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:**

| Parameter          | Type           | Required | Description                                                     |
| ------------------ | -------------- | -------- | --------------------------------------------------------------- |
| `eventName`        | `string`       | Yes      | Event name in snake\_case (e.g., `'add_to_cart'`, `'purchase'`) |
| `eventData`        | `object`       | No       | Event properties                                                |
| `eventId`          | `string`       | No       | Unique ID for deduplication across destinations                 |
| `contextOverride`  | `object`       | No       | Override page/session context for this event                    |
| `collectedAt`      | `string`       | No       | ISO 8601 timestamp for backdated events                         |
| `collectedAtEpoch` | `number`       | No       | Unix epoch milliseconds for backdated events                    |
| `options`          | `TrackOptions` | No       | `{ useBeacon: boolean }` for page unload tracking               |

**Shorthand for useBeacon:**

When the 4th argument is an object with `useBeacon`, it's treated as options:

```javascript theme={null}
// 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:**

```javascript theme={null}
// 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.

```typescript theme={null}
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:**

| Parameter | Type                  | Required | Description                                                                       |
| --------- | --------------------- | -------- | --------------------------------------------------------------------------------- |
| `userId`  | `string \| null`      | No       | Your internal user ID. Pass `null` for anonymous identification with traits only. |
| `data`    | `EventIdentityTraits` | No       | Identity traits with `emails[]` and `phones[]` as arrays                          |

<Note>
  **Important:** `emails` and `phones` are arrays, not single values. This supports users with multiple contact methods.
</Note>

**Examples:**

```javascript theme={null}
// 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.

```typescript theme={null}
function metric(
  metricName: string,
  metricValue: number,
  metricData?: Record<string, unknown>,
  metricId?: string
): null
```

<Warning>
  **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.
</Warning>

**Parameters:**

| Parameter     | Type     | Required | Description                 |
| ------------- | -------- | -------- | --------------------------- |
| `metricName`  | `string` | Yes      | Metric name                 |
| `metricValue` | `number` | Yes      | Numeric value               |
| `metricData`  | `object` | No       | Additional context          |
| `metricId`    | `string` | No       | Unique ID for deduplication |

**Example:**

```javascript theme={null}
// 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.

```typescript theme={null}
function reset(): void
```

**Example:**

```javascript theme={null}
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.

```typescript theme={null}
function isKnown(): Promise<boolean>
```

**Returns:** Promise resolving to `true` if the user has been identified, `false` otherwise.

<Warning>
  **Direct Client Only:** This method is NOT available via the `_upstack()` queue. You must call it directly on `window._upsClient`.
</Warning>

**Example:**

```javascript theme={null}
// After init completes
const isKnown = await window._upsClient.isKnown();
if (!isKnown) {
  showEmailCapturePopup();
}
```

***

### getUpstackId()

Retrieve the Upstack identity object for the current user.

```typescript theme={null}
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).

<Warning>
  **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.
</Warning>

**Example:**

```javascript theme={null}
// 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:

```javascript theme={null}
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:

```javascript theme={null}
// 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:

```javascript theme={null}
// 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:

```javascript theme={null}
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:

```javascript theme={null}
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:

```typescript theme={null}
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

## Related Documentation

<CardGroup cols={2}>
  <Card title="Pixel Setup" icon="download" href="/pixel/setup">
    Installation guide for non-Shopify websites and SPAs.
  </Card>

  <Card title="Standard Events" icon="list-check" href="/pixel/standard-events">
    Complete reference for all standard events with JavaScript snippets.
  </Card>

  <Card title="Properties & Context" icon="table" href="/pixel/events/event-properties">
    Reference for item arrays, customer data, and auto-captured fields.
  </Card>

  <Card title="Custom Events" icon="sparkles" href="/pixel/custom-events">
    Create events beyond the standard taxonomy for your needs.
  </Card>

  <Card title="Identity Resolution" icon="fingerprint" href="/pixel/identity-resolution">
    How identify() connects sessions to customer profiles.
  </Card>

  <Card title="Shopify Automatic Tracking" icon="shopify" href="/sources/shopify-automatic-tracking">
    Events tracked automatically on Shopify stores.
  </Card>
</CardGroup>
