> ## 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.

# SaaS & B2B Events Reference

> Track SaaS events with Upstack Data — subscription lifecycle, trials, payments, seat expansion, and user engagement with copyable JavaScript snippets.

<Info>
  These events are designed for **B2B SaaS** and **subscription-based businesses**.
  If you're running an e-commerce store, see [Standard Events](/pixel/standard-events) instead.
</Info>

## When to Use SaaS Events

Use these events when your business model includes:

* **Subscription billing** (monthly/annual plans)
* **Free trials** with conversion tracking
* **Seat-based pricing** with expansion revenue
* **Multi-user accounts** with role-based access
* **Product-led growth** with feature usage tracking

***

## Account Lifecycle

Track account creation and deletion to measure growth and churn.

### account\_created

Fires when a new account (organization/workspace) is created.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'account_created', {
  accountId: 'acct_abc123',
  accountName: 'Acme Corporation',
  planId: 'plan_starter_monthly',
  planName: 'Starter',
  userId: 'usr_xyz789',
  userEmail: 'jane@acme.com'
});
```

#### Properties

| Property    | Type   | Required | Description               |
| ----------- | ------ | -------- | ------------------------- |
| accountId   | string | Yes      | Unique account identifier |
| accountName | string | No       | Account/organization name |
| planId      | string | No       | Initial plan identifier   |
| planName    | string | No       | Initial plan name         |
| userId      | string | No       | Creating user's ID        |
| userEmail   | string | No       | Creating user's email     |

#### When to Fire

* After account registration completes
* After organization setup wizard finishes
* After SSO provisioning creates a new workspace

***

### account\_deleted

Fires when an account is permanently deleted.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'account_deleted', {
  accountId: 'acct_abc123',
  accountName: 'Acme Corporation',
  cancelReason: 'no_longer_needed',
  cancelFeedback: 'Switching to a different solution',
  mrr: 9900
});
```

#### Properties

| Property       | Type   | Required | Description                |
| -------------- | ------ | -------- | -------------------------- |
| accountId      | string | Yes      | Deleted account identifier |
| accountName    | string | No       | Account name               |
| cancelReason   | string | No       | Reason code for deletion   |
| cancelFeedback | string | No       | User-provided feedback     |
| mrr            | number | No       | Lost MRR in cents          |

#### When to Fire

* After account deletion confirmation
* After workspace removal completes
* After data retention period expires

***

## Acquisition

Track the lead-to-signup funnel to measure conversion rates.

### signup\_started

Fires when a user begins the signup flow.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'signup_started', {
  planId: 'plan_pro_monthly',
  source: 'pricing_page'
});
```

#### Properties

| Property | Type   | Required | Description                       |
| -------- | ------ | -------- | --------------------------------- |
| planId   | string | No       | Pre-selected plan (if applicable) |
| source   | string | No       | Where signup was initiated        |

#### When to Fire

* When signup form is opened
* When registration page loads
* When "Start Free Trial" button is clicked

***

### signup\_completed

Fires when a user completes signup and creates an account.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'signup_completed', {
  userId: 'usr_xyz789',
  accountId: 'acct_abc123',
  userEmail: 'jane@acme.com',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan'
});
```

#### Properties

| Property  | Type   | Required | Description            |
| --------- | ------ | -------- | ---------------------- |
| userId    | string | Yes      | New user identifier    |
| accountId | string | Yes      | New account identifier |
| userEmail | string | No       | User email address     |
| planId    | string | No       | Selected plan          |
| planName  | string | No       | Plan display name      |

#### When to Fire

* After signup form submission succeeds
* After email verification completes
* After OAuth signup flow finishes

***

### demo\_requested

Fires when a user requests a product demo.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'demo_requested', {
  userEmail: 'buyer@enterprise.com',
  companyName: 'Enterprise Corp',
  companySize: '500-1000',
  useCase: 'marketing_analytics'
});
```

#### Properties

| Property    | Type   | Required | Description        |
| ----------- | ------ | -------- | ------------------ |
| userEmail   | string | No       | Requester email    |
| companyName | string | No       | Company name       |
| companySize | string | No       | Company size range |
| useCase     | string | No       | Primary use case   |

#### When to Fire

* After demo request form submission
* After sales call booking confirmation
* After Calendly/HubSpot meeting scheduled

***

## Trial Events

Track the trial lifecycle from start to conversion or expiry.

### trial\_started

Fires when a user begins a free trial.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_started', {
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  trialEndDate: '2026-03-04T14:30:00.000Z',
  trialDaysRemaining: 14
});
```

#### Properties

| Property           | Type   | Required | Description                    |
| ------------------ | ------ | -------- | ------------------------------ |
| accountId          | string | Yes      | Account identifier             |
| planId             | string | Yes      | Trial plan identifier          |
| planName           | string | No       | Human-readable plan name       |
| trialEndDate       | string | No       | ISO 8601 trial expiration date |
| trialDaysRemaining | number | No       | Days until trial expires       |

#### When to Fire

* After trial signup confirmation
* After trial activation in billing system
* After Stripe `customer.subscription.created` with trial

***

### trial\_activated

Fires when a trial user reaches a meaningful activation milestone.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_activated', {
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  trialDaysRemaining: 12,
  activationMilestone: 'first_integration_connected'
});
```

#### Properties

| Property            | Type   | Required | Description                 |
| ------------------- | ------ | -------- | --------------------------- |
| accountId           | string | Yes      | Account identifier          |
| planId              | string | No       | Trial plan identifier       |
| trialDaysRemaining  | number | No       | Days remaining in trial     |
| activationMilestone | string | No       | Which milestone was reached |

#### When to Fire

* After first key feature is used
* After onboarding checklist is completed
* After first data import succeeds

***

### trial\_extended

Fires when a trial period is extended.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_extended', {
  accountId: 'acct_abc123',
  trialEndDate: '2026-03-11T14:30:00.000Z',
  trialDaysRemaining: 7,
  extensionReason: 'support_request'
});
```

#### Properties

| Property           | Type   | Required | Description            |
| ------------------ | ------ | -------- | ---------------------- |
| accountId          | string | Yes      | Account identifier     |
| trialEndDate       | string | No       | New trial end date     |
| trialDaysRemaining | number | No       | New days remaining     |
| extensionReason    | string | No       | Why trial was extended |

#### When to Fire

* After support manually extends trial
* After promotional extension is applied
* After win-back campaign grants extension

***

### trial\_ending\_soon

Fires when a trial is about to expire (typically 3 days before).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_ending_soon', {
  accountId: 'acct_abc123',
  trialDaysRemaining: 3,
  planId: 'plan_pro_monthly',
  trialEndDate: '2026-03-04T14:30:00.000Z'
});
```

#### Properties

| Property           | Type   | Required | Description           |
| ------------------ | ------ | -------- | --------------------- |
| accountId          | string | Yes      | Account identifier    |
| trialDaysRemaining | number | Yes      | Days until expiry     |
| planId             | string | No       | Trial plan identifier |
| trialEndDate       | string | No       | Trial expiration date |

#### When to Fire

* 3 days before trial expires (common)
* When Stripe sends `customer.subscription.trial_will_end`
* When automated warning email triggers

***

### trial\_expired

Fires when a trial ends without conversion.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_expired', {
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  trialDays: 14
});
```

#### Properties

| Property  | Type   | Required | Description        |
| --------- | ------ | -------- | ------------------ |
| accountId | string | Yes      | Account identifier |
| planId    | string | No       | Expired trial plan |
| planName  | string | No       | Plan display name  |
| trialDays | number | No       | Total trial length |

#### When to Fire

* When trial end date is reached without payment
* When account is downgraded to free tier
* When access is revoked after grace period

***

### trial\_converted

Fires when a trial converts to a paid subscription. This is a key conversion event.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'trial_converted', {
  accountId: 'acct_abc123',
  subscriptionId: 'sub_def456',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  mrr: 9900,
  billingInterval: 'month'
});
```

#### Properties

| Property        | Type   | Required | Description                        |
| --------------- | ------ | -------- | ---------------------------------- |
| accountId       | string | Yes      | Account identifier                 |
| subscriptionId  | string | Yes      | New subscription ID                |
| planId          | string | Yes      | Converted plan identifier          |
| planName        | string | No       | Plan display name                  |
| mrr             | number | No       | Monthly recurring revenue in cents |
| billingInterval | string | No       | `month` or `year`                  |

#### When to Fire

* After first successful payment
* When Stripe subscription status changes from `trialing` to `active`
* After payment method is charged successfully

<Tip>
  Track `mrr` to measure trial-to-paid conversion value and calculate average revenue per converted trial.
</Tip>

***

## Subscription Lifecycle

Track the complete subscription journey from creation through churn or reactivation.

### subscription\_created

Fires when a subscription record is created in your billing system.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_created', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  billingInterval: 'month'
});
```

#### Properties

| Property        | Type   | Required | Description                       |
| --------------- | ------ | -------- | --------------------------------- |
| subscriptionId  | string | Yes      | Subscription identifier           |
| accountId       | string | Yes      | Account identifier                |
| planId          | string | Yes      | Plan identifier                   |
| planName        | string | No       | Plan display name                 |
| billingInterval | string | No       | `day`, `week`, `month`, or `year` |

#### When to Fire

* When subscription object is created in Stripe
* May precede first payment (for trials)
* After checkout session completes

***

### subscription\_started

Fires when a new subscription begins (first billing period starts).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_started', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  mrr: 9900,
  billingInterval: 'month'
});
```

#### Properties

| Property        | Type   | Required | Description                        |
| --------------- | ------ | -------- | ---------------------------------- |
| subscriptionId  | string | Yes      | Subscription identifier            |
| accountId       | string | Yes      | Account identifier                 |
| planId          | string | Yes      | Plan identifier                    |
| planName        | string | No       | Plan display name                  |
| mrr             | number | No       | Monthly recurring revenue in cents |
| billingInterval | string | No       | Billing frequency                  |

#### When to Fire

* After first successful charge
* When subscription status becomes `active`
* After trial converts to paid

***

### subscription\_upgraded

Fires when a customer upgrades to a higher-tier plan.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_upgraded', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_business_monthly',
  planName: 'Business',
  previousPlanId: 'plan_pro_monthly',
  mrr: 19900,
  mrrDelta: 10000
});
```

#### Properties

| Property       | Type   | Required | Description                      |
| -------------- | ------ | -------- | -------------------------------- |
| subscriptionId | string | Yes      | Subscription identifier          |
| accountId      | string | Yes      | Account identifier               |
| planId         | string | No       | New plan identifier              |
| planName       | string | No       | New plan name                    |
| previousPlanId | string | No       | Previous plan identifier         |
| mrr            | number | No       | New MRR after upgrade in cents   |
| mrrDelta       | number | No       | MRR increase in cents (positive) |

#### When to Fire

* When plan changes from lower to higher tier
* When Stripe subscription item is updated with higher-priced plan
* After upgrade checkout completes

<Tip>
  Track `mrrDelta` alongside `subscription_downgraded` to calculate net revenue retention.
</Tip>

***

### subscription\_downgraded

Fires when a customer downgrades to a lower-tier plan.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_downgraded', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_starter_monthly',
  planName: 'Starter',
  previousPlanId: 'plan_pro_monthly',
  mrr: 4900,
  mrrDelta: -5000
});
```

#### Properties

| Property       | Type   | Required | Description                      |
| -------------- | ------ | -------- | -------------------------------- |
| subscriptionId | string | Yes      | Subscription identifier          |
| accountId      | string | Yes      | Account identifier               |
| planId         | string | No       | New plan identifier              |
| planName       | string | No       | New plan name                    |
| previousPlanId | string | No       | Previous plan identifier         |
| mrr            | number | No       | New MRR after downgrade in cents |
| mrrDelta       | number | No       | MRR decrease in cents (negative) |

#### When to Fire

* When plan changes from higher to lower tier
* When features are removed from subscription
* When scheduled downgrade takes effect at period end

***

### subscription\_renewed

<Note>
  This is a **custom event name**. For standard renewal tracking, consider using `payment_succeeded` or `invoice_paid` events instead.
</Note>

Fires when a subscription successfully renews for another billing period.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_renewed', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  mrr: 9900,
  renewalCount: 6
});
```

#### Properties

| Property       | Type   | Required | Description             |
| -------------- | ------ | -------- | ----------------------- |
| subscriptionId | string | Yes      | Subscription identifier |
| accountId      | string | Yes      | Account identifier      |
| planId         | string | No       | Current plan identifier |
| mrr            | number | No       | Renewed MRR in cents    |
| renewalCount   | number | No       | Number of times renewed |

#### When to Fire

* When recurring payment succeeds
* When billing period advances
* When Stripe `invoice.paid` fires for subscription

***

### subscription\_paused

Fires when a subscription is paused.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_paused', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  mrr: 9900,
  pauseReason: 'seasonal_business'
});
```

#### Properties

| Property       | Type   | Required | Description                 |
| -------------- | ------ | -------- | --------------------------- |
| subscriptionId | string | Yes      | Subscription identifier     |
| accountId      | string | Yes      | Account identifier          |
| planId         | string | No       | Plan identifier             |
| mrr            | number | No       | Paused MRR in cents         |
| pauseReason    | string | No       | Why subscription was paused |

#### When to Fire

* When customer requests pause
* When seasonal pause is activated
* When Stripe subscription pause feature triggers

***

### subscription\_resumed

Fires when a paused subscription is resumed.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_resumed', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  mrr: 9900,
  pausedDays: 30
});
```

#### Properties

| Property       | Type   | Required | Description                      |
| -------------- | ------ | -------- | -------------------------------- |
| subscriptionId | string | Yes      | Subscription identifier          |
| accountId      | string | Yes      | Account identifier               |
| planId         | string | No       | Plan identifier                  |
| mrr            | number | No       | Resumed MRR in cents             |
| pausedDays     | number | No       | How long subscription was paused |

#### When to Fire

* When customer manually resumes
* When pause period ends automatically
* When billing restarts

***

### subscription\_cancelled

Fires when a cancellation is requested (may still be active until period end).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_cancelled', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  cancelReason: 'too_expensive',
  cancelFeedback: 'Budget constraints this quarter',
  mrr: 9900,
  cancelAtPeriodEnd: true
});
```

#### Properties

| Property          | Type    | Required | Description                               |
| ----------------- | ------- | -------- | ----------------------------------------- |
| subscriptionId    | string  | Yes      | Subscription identifier                   |
| accountId         | string  | Yes      | Account identifier                        |
| planId            | string  | No       | Cancelled plan                            |
| cancelReason      | string  | No       | Cancellation reason code                  |
| cancelFeedback    | string  | No       | User-provided feedback                    |
| mrr               | number  | No       | MRR being cancelled in cents              |
| cancelAtPeriodEnd | boolean | No       | If true, cancels at end of billing period |

#### When to Fire

* When customer clicks cancel button
* When cancellation request is submitted
* When Stripe subscription is set to cancel at period end

***

### subscription\_churned

Fires when a subscription ends completely (no longer billing). This is the final churn event.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_churned', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  cancelReason: 'switched_competitor',
  mrr: 9900,
  ltv: 118800,
  subscriptionMonths: 12
});
```

#### Properties

| Property           | Type   | Required | Description                      |
| ------------------ | ------ | -------- | -------------------------------- |
| subscriptionId     | string | Yes      | Subscription identifier          |
| accountId          | string | Yes      | Account identifier               |
| planId             | string | No       | Churned plan                     |
| cancelReason       | string | No       | Churn reason                     |
| mrr                | number | No       | Lost MRR in cents                |
| ltv                | number | No       | Customer lifetime value in cents |
| subscriptionMonths | number | No       | How long they were subscribed    |

#### When to Fire

* When final billing period ends
* When subscription is deactivated
* When Stripe `customer.subscription.deleted` fires

<Warning>
  Use this event to calculate churn rate and analyze churn reasons. Track `ltv` to understand which customer segments have the highest lifetime value.
</Warning>

***

### subscription\_initial\_purchase

Fires when a customer's first subscription payment is processed (distinct from trial conversion).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_initial_purchase', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  value: 9900,
  currency: 'USD',
  billingInterval: 'month'
});
```

#### Properties

| Property        | Type   | Required | Description             |
| --------------- | ------ | -------- | ----------------------- |
| subscriptionId  | string | Yes      | Subscription identifier |
| accountId       | string | Yes      | Account identifier      |
| planId          | string | No       | Plan identifier         |
| planName        | string | No       | Plan display name       |
| value           | number | No       | Payment amount in cents |
| currency        | string | No       | ISO 4217 currency code  |
| billingInterval | string | No       | `month` or `year`       |

#### When to Fire

* First subscription charge succeeds
* After trial converts (first paid billing period)
* When new customer's initial payment processes

***

### subscription\_recurring\_purchase

Fires when a recurring subscription payment is processed (not the initial purchase).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_recurring_purchase', {
  subscriptionId: 'sub_def456',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  value: 9900,
  currency: 'USD',
  billingInterval: 'month',
  renewalNumber: 6
});
```

#### Properties

| Property        | Type   | Required | Description                            |
| --------------- | ------ | -------- | -------------------------------------- |
| subscriptionId  | string | Yes      | Subscription identifier                |
| accountId       | string | Yes      | Account identifier                     |
| planId          | string | No       | Plan identifier                        |
| planName        | string | No       | Plan display name                      |
| value           | number | No       | Payment amount in cents                |
| currency        | string | No       | ISO 4217 currency code                 |
| billingInterval | string | No       | `month` or `year`                      |
| renewalNumber   | number | No       | Which renewal this is (2nd, 3rd, etc.) |

#### When to Fire

* Each recurring billing cycle
* When Stripe `invoice.paid` fires for an existing subscription
* Monthly/annual renewal charge succeeds

<Tip>
  Use `subscription_initial_purchase` for acquisition metrics and `subscription_recurring_purchase` for retention/LTV analysis. Together they give a complete picture of subscription revenue.
</Tip>

***

### subscription\_reactivated

Fires when a previously churned customer resubscribes.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'subscription_reactivated', {
  subscriptionId: 'sub_ghi789',
  accountId: 'acct_abc123',
  planId: 'plan_pro_monthly',
  planName: 'Pro Plan',
  mrr: 9900,
  daysSinceChurn: 45
});
```

#### Properties

| Property       | Type   | Required | Description                         |
| -------------- | ------ | -------- | ----------------------------------- |
| subscriptionId | string | Yes      | New subscription identifier         |
| accountId      | string | Yes      | Account identifier                  |
| planId         | string | No       | New plan identifier                 |
| planName       | string | No       | Plan display name                   |
| mrr            | number | No       | Recovered MRR in cents              |
| daysSinceChurn | number | No       | Days between churn and reactivation |

#### When to Fire

* When former customer signs up again
* When win-back campaign converts
* When churned account starts new subscription

***

## Order Fulfillment Events

Track order fulfillment and shipping for e-commerce subscription boxes, physical product deliveries, and Klaviyo flow triggers.

### order\_fulfilled

Fires when an order has been completely fulfilled (all items prepared for shipment).

#### JavaScript

```javascript theme={null}
window._upstack('track', 'order_fulfilled', {
  orderId: 'ORD_12345',
  orderName: '#1042',
  value: 149.99,
  currency: 'USD',
  fulfillmentStatus: 'fulfilled',
  items: [
    {
      id: 'SKU_001',
      name: 'Monthly Snack Box',
      price: 39.99,
      quantity: 1
    }
  ],
  email: 'customer@example.com'
});
```

#### Properties

| Property          | Type   | Required | Description                                           |
| ----------------- | ------ | -------- | ----------------------------------------------------- |
| orderId           | string | Yes      | Order identifier                                      |
| orderName         | string | No       | Human-readable order name                             |
| value             | number | No       | Order value                                           |
| currency          | string | No       | ISO 4217 currency code                                |
| fulfillmentStatus | string | No       | Fulfillment status (e.g., `'fulfilled'`, `'partial'`) |
| items             | array  | No       | Products fulfilled                                    |
| email             | string | No       | Customer email                                        |

#### When to Fire

* When warehouse marks order as packed/ready
* When Shopify fulfillment is created
* When all items in an order are fulfilled

***

### order\_shipped

Fires when an order has been shipped and tracking information is available.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'order_shipped', {
  orderId: 'ORD_12345',
  orderName: '#1042',
  value: 149.99,
  currency: 'USD',
  trackingNumber: '1Z999AA10123456784',
  trackingCompany: 'UPS',
  trackingUrl: 'https://www.ups.com/track?tracknum=1Z999AA10123456784',
  estimatedDelivery: '2026-02-25T00:00:00.000Z',
  items: [
    {
      id: 'SKU_001',
      name: 'Monthly Snack Box',
      price: 39.99,
      quantity: 1
    }
  ],
  email: 'customer@example.com'
});
```

#### Properties

| Property          | Type   | Required | Description                                           |
| ----------------- | ------ | -------- | ----------------------------------------------------- |
| orderId           | string | Yes      | Order identifier                                      |
| orderName         | string | No       | Human-readable order name                             |
| value             | number | No       | Order value                                           |
| currency          | string | No       | ISO 4217 currency code                                |
| trackingNumber    | string | No       | Carrier tracking number                               |
| trackingCompany   | string | No       | Shipping carrier (e.g., `'UPS'`, `'FedEx'`, `'USPS'`) |
| trackingUrl       | string | No       | Direct link to tracking page                          |
| estimatedDelivery | string | No       | ISO 8601 estimated delivery date                      |
| items             | array  | No       | Products shipped                                      |
| email             | string | No       | Customer email                                        |

#### When to Fire

* When shipping label is created with tracking
* When carrier picks up package
* When Shopify `fulfillment_events/create` webhook fires

<Tip>
  **Klaviyo integration:** `order_shipped` is commonly used to trigger post-purchase flows like "Your order is on the way" emails with tracking information.
</Tip>

***

## User Events

Track team growth and user engagement within accounts.

### user\_invited

Fires when a user is invited to join an account.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'user_invited', {
  accountId: 'acct_abc123',
  inviteeEmail: 'newmember@acme.com',
  inviteeRole: 'member',
  invitedByUserId: 'usr_xyz789'
});
```

#### Properties

| Property        | Type   | Required | Description           |
| --------------- | ------ | -------- | --------------------- |
| accountId       | string | Yes      | Account identifier    |
| inviteeEmail    | string | No       | Invitee email address |
| inviteeRole     | string | No       | Assigned role         |
| invitedByUserId | string | No       | Inviter's user ID     |

#### When to Fire

* When team invite is sent
* When collaboration request is initiated
* After invite email is dispatched

***

### user\_joined

Fires when an invited user accepts and joins the account.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'user_joined', {
  userId: 'usr_newmember',
  accountId: 'acct_abc123',
  userEmail: 'newmember@acme.com',
  userRole: 'member'
});
```

#### Properties

| Property  | Type   | Required | Description          |
| --------- | ------ | -------- | -------------------- |
| userId    | string | Yes      | New user identifier  |
| accountId | string | Yes      | Account identifier   |
| userEmail | string | No       | User email address   |
| userRole  | string | No       | User's assigned role |

#### When to Fire

* When invite is accepted
* When account access is granted
* After user completes join flow

***

### user\_role\_changed

<Note>
  This is a **custom event name**. Track it using the [Custom Events](/pixel/custom-events) pattern if you need role change analytics.
</Note>

Fires when a user's role is changed within an account.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'user_role_changed', {
  userId: 'usr_xyz789',
  accountId: 'acct_abc123',
  previousRole: 'member',
  newRole: 'admin',
  changedByUserId: 'usr_admin123'
});
```

#### Properties

| Property        | Type   | Required | Description               |
| --------------- | ------ | -------- | ------------------------- |
| userId          | string | Yes      | User whose role changed   |
| accountId       | string | Yes      | Account identifier        |
| previousRole    | string | No       | Previous role             |
| newRole         | string | No       | New role                  |
| changedByUserId | string | No       | Admin who made the change |

#### When to Fire

* When user is promoted to admin
* When permissions are modified
* After role update is saved

***

## Billing Events

Track payment activity for revenue analytics and dunning workflows.

### payment\_succeeded

Fires when a payment is processed successfully.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'payment_succeeded', {
  accountId: 'acct_abc123',
  invoiceId: 'inv_ghi012',
  subscriptionId: 'sub_def456',
  amount: 9900,
  currency: 'USD'
});
```

#### Properties

| Property       | Type   | Required | Description             |
| -------------- | ------ | -------- | ----------------------- |
| accountId      | string | Yes      | Account identifier      |
| amount         | number | Yes      | Payment amount in cents |
| invoiceId      | string | No       | Invoice identifier      |
| subscriptionId | string | No       | Subscription identifier |
| currency       | string | No       | ISO 4217 currency code  |

#### When to Fire

* When charge succeeds
* When invoice is paid
* When Stripe `invoice.paid` webhook fires

***

### payment\_failed

Fires when a payment attempt fails.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'payment_failed', {
  accountId: 'acct_abc123',
  invoiceId: 'inv_ghi012',
  subscriptionId: 'sub_def456',
  amount: 9900,
  failureReason: 'card_declined',
  failureCode: 'insufficient_funds',
  currency: 'USD'
});
```

#### Properties

| Property       | Type   | Required | Description                    |
| -------------- | ------ | -------- | ------------------------------ |
| accountId      | string | Yes      | Account identifier             |
| amount         | number | Yes      | Failed payment amount in cents |
| invoiceId      | string | No       | Invoice identifier             |
| subscriptionId | string | No       | Subscription identifier        |
| failureReason  | string | No       | Failure reason code            |
| failureCode    | string | No       | Detailed failure code          |
| currency       | string | No       | ISO 4217 currency code         |

#### When to Fire

* When card is declined
* When insufficient funds error occurs
* When Stripe `invoice.payment_failed` webhook fires

<Warning>
  Track payment failures to identify at-risk customers and trigger dunning workflows.
</Warning>

***

### invoice\_paid

Fires when an invoice is marked as paid.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'invoice_paid', {
  accountId: 'acct_abc123',
  invoiceId: 'inv_ghi012',
  subscriptionId: 'sub_def456',
  amount: 9900,
  currency: 'USD'
});
```

#### Properties

| Property       | Type   | Required | Description             |
| -------------- | ------ | -------- | ----------------------- |
| accountId      | string | Yes      | Account identifier      |
| invoiceId      | string | Yes      | Invoice identifier      |
| amount         | number | Yes      | Paid amount in cents    |
| subscriptionId | string | No       | Subscription identifier |
| currency       | string | No       | ISO 4217 currency code  |

#### When to Fire

* When payment is received
* When manual reconciliation marks invoice paid
* When Stripe `invoice.paid` webhook fires

***

## Expansion Events

Track seat-based and add-on revenue expansion.

### seat\_added

Fires when additional seats are purchased.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'seat_added', {
  accountId: 'acct_abc123',
  subscriptionId: 'sub_def456',
  seatCount: 15,
  seatDelta: 5,
  mrrDelta: 2500
});
```

#### Properties

| Property       | Type   | Required | Description                      |
| -------------- | ------ | -------- | -------------------------------- |
| accountId      | string | Yes      | Account identifier               |
| seatCount      | number | Yes      | Total seats after addition       |
| subscriptionId | string | No       | Subscription identifier          |
| seatDelta      | number | No       | Number of seats added            |
| mrrDelta       | number | No       | MRR increase from seats in cents |

#### When to Fire

* When seats are purchased
* When user is added beyond plan limit
* When Stripe subscription quantity increases

***

### seat\_removed

Fires when seats are removed from the plan.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'seat_removed', {
  accountId: 'acct_abc123',
  subscriptionId: 'sub_def456',
  seatCount: 10,
  seatDelta: -5,
  mrrDelta: -2500
});
```

#### Properties

| Property       | Type   | Required | Description                        |
| -------------- | ------ | -------- | ---------------------------------- |
| accountId      | string | Yes      | Account identifier                 |
| seatCount      | number | Yes      | Total seats after removal          |
| subscriptionId | string | No       | Subscription identifier            |
| seatDelta      | number | No       | Number of seats removed (negative) |
| mrrDelta       | number | No       | MRR decrease in cents (negative)   |

#### When to Fire

* When seats are removed
* When user is deactivated
* When Stripe subscription quantity decreases

***

## Engagement Events

Track user activity and product milestones.

### feature\_used

Fires when a specific feature is used. Track key features to understand product adoption.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'feature_used', {
  accountId: 'acct_abc123',
  userId: 'usr_xyz789',
  featureId: 'feat_export',
  featureName: 'CSV Export',
  featureCategory: 'reporting'
});
```

#### Properties

| Property        | Type   | Required | Description               |
| --------------- | ------ | -------- | ------------------------- |
| accountId       | string | Yes      | Account identifier        |
| featureId       | string | Yes      | Feature identifier        |
| userId          | string | No       | User who used the feature |
| featureName     | string | No       | Feature display name      |
| featureCategory | string | No       | Feature category          |

#### When to Fire

* When key features are used
* When premium features are accessed
* When usage-based actions are performed

***

### milestone\_reached

Fires when a key milestone is achieved.

#### JavaScript

```javascript theme={null}
window._upstack('track', 'milestone_reached', {
  accountId: 'acct_abc123',
  milestoneId: 'milestone_100_orders',
  milestoneName: '100 Orders Processed',
  milestoneValue: 100
});
```

#### Properties

| Property       | Type   | Required | Description            |
| -------------- | ------ | -------- | ---------------------- |
| accountId      | string | Yes      | Account identifier     |
| milestoneId    | string | Yes      | Milestone identifier   |
| milestoneName  | string | No       | Milestone display name |
| milestoneValue | number | No       | Numeric value achieved |

#### When to Fire

* When usage threshold is crossed
* When achievement is unlocked
* When significant product milestone occurs

***

## Stripe Webhook Integration

If you use Stripe for billing, handle webhooks to track events automatically.

<Warning>
  Webhook handlers run server-side where `window._upstack()` is not available. Server-side event tracking requires the Upstack Server API. Contact support for early access, or use the patterns below to queue events for client-side tracking.
</Warning>

### Server-Side Helper Pattern

Create a helper to queue events for server-side tracking:

```javascript theme={null}
// utils/tracking.js
async function trackServerEvent(eventName, properties) {
  // Option 1: Direct API call (requires Server API access)
  await fetch('https://api.getupstack.com/v1/events', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.UPSTACK_API_KEY}`
    },
    body: JSON.stringify({
      event: eventName,
      properties,
      timestamp: new Date().toISOString()
    })
  });
  
  // Option 2: Store in database for later sync
  // await db.pendingEvents.create({ eventName, properties });
}
```

### Example Webhook Handler

```javascript theme={null}
// Express.js webhook handler (server-side)
app.post('/webhooks/stripe', async (req, res) => {
  const event = stripe.webhooks.constructEvent(
    req.body,
    req.headers['stripe-signature'],
    process.env.STRIPE_WEBHOOK_SECRET
  );

  switch (event.type) {
    case 'customer.subscription.created':
      const sub = event.data.object;
      await trackServerEvent('subscription_created', {
        subscriptionId: sub.id,
        accountId: sub.metadata.account_id,
        planId: sub.items.data[0].price.id,
        billingInterval: sub.items.data[0].price.recurring.interval
      });
      break;

    case 'customer.subscription.updated':
      const updated = event.data.object;
      const previous = event.data.previous_attributes;
      
      if (previous.items) {
        const newPrice = updated.items.data[0].price.unit_amount;
        const oldPrice = previous.items.data[0].price.unit_amount;
        
        if (newPrice > oldPrice) {
          await trackServerEvent('subscription_upgraded', {
            subscriptionId: updated.id,
            accountId: updated.metadata.account_id,
            planId: updated.items.data[0].price.id,
            mrrDelta: newPrice - oldPrice
          });
        } else {
          await trackServerEvent('subscription_downgraded', {
            subscriptionId: updated.id,
            accountId: updated.metadata.account_id,
            planId: updated.items.data[0].price.id,
            mrrDelta: newPrice - oldPrice
          });
        }
      }
      break;

    case 'customer.subscription.deleted':
      const deleted = event.data.object;
      await trackServerEvent('subscription_churned', {
        subscriptionId: deleted.id,
        accountId: deleted.metadata.account_id,
        planId: deleted.items.data[0].price.id,
        mrr: deleted.items.data[0].price.unit_amount
      });
      break;

    case 'invoice.paid':
      const invoice = event.data.object;
      await trackServerEvent('payment_succeeded', {
        accountId: invoice.metadata.account_id,
        invoiceId: invoice.id,
        subscriptionId: invoice.subscription,
        amount: invoice.amount_paid,
        currency: invoice.currency.toUpperCase()
      });
      break;

    case 'invoice.payment_failed':
      const failed = event.data.object;
      await trackServerEvent('payment_failed', {
        accountId: failed.metadata.account_id,
        invoiceId: failed.id,
        subscriptionId: failed.subscription,
        amount: failed.amount_due,
        failureReason: failed.last_payment_error?.code
      });
      break;

    case 'customer.subscription.trial_will_end':
      const trial = event.data.object;
      await trackServerEvent('trial_ending_soon', {
        accountId: trial.metadata.account_id,
        trialDaysRemaining: 3,
        planId: trial.items.data[0].price.id,
        trialEndDate: new Date(trial.trial_end * 1000).toISOString()
      });
      break;
  }

  res.json({ received: true });
});
```

### Stripe Webhook Mapping

| Stripe Webhook                         | Upstack Event                                       |
| -------------------------------------- | --------------------------------------------------- |
| `customer.subscription.created`        | `subscription_created`                              |
| `customer.subscription.updated`        | `subscription_upgraded` / `subscription_downgraded` |
| `customer.subscription.deleted`        | `subscription_churned`                              |
| `customer.subscription.paused`         | `subscription_paused`                               |
| `customer.subscription.resumed`        | `subscription_resumed`                              |
| `invoice.paid`                         | `invoice_paid`, `payment_succeeded`                 |
| `invoice.payment_failed`               | `payment_failed`                                    |
| `customer.subscription.trial_will_end` | `trial_ending_soon`                                 |
| `charge.refunded`                      | `payment_refunded`                                  |

***

## What's Next

<CardGroup cols={2}>
  <Card title="Standard Events" icon="list-check" href="/pixel/standard-events">
    E-commerce event reference for Shopify stores.
  </Card>

  <Card title="Custom Events" icon="code" href="/pixel/custom-events">
    Define your own events beyond the standard taxonomy.
  </Card>

  <Card title="Properties & Context" icon="table" href="/pixel/events/event-properties">
    Complete reference for all event fields.
  </Card>

  <Card title="Event Taxonomy" icon="sitemap" href="/pixel/events/taxonomy">
    How events flow through the Upstack pipeline.
  </Card>
</CardGroup>
