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

# Event Tracking

> Track custom events with the Permutive JavaScript SDK

Use `track()`, `on()`, and `once()` to track custom events and listen for SDK events.

<CardGroup cols={3}>
  <Card title="track()" href="#tracking-events" icon="bolt" />

  <Card title="on() / once()" href="#event-listeners" icon="bell" />

  <Card title="Event Types" href="#standard-event-types" icon="list" />
</CardGroup>

## Tracking Events

### Basic Usage

```javascript theme={"dark"}
permutive.track('EventName', {
  property1: 'value',
  property2: 123
});
```

### With Callback

```javascript theme={"dark"}
permutive.track('Purchase', {
  product_id: 'SKU123',
  price: 29.99
}, {
  success: function(event) {
    console.log('Event tracked:', event);
  },
  error: function(errorType, errorMsg) {
    console.error('Tracking failed:', errorType, errorMsg);
  }
});
```

### With Beacon API

Force use of the Beacon API for reliable tracking during page unload:

```javascript theme={"dark"}
permutive.track('PageExit', {
  time_on_page: 120
}, {
  useBeacon: true
});
```

## track() Method

### Signature

```javascript theme={"dark"}
permutive.track(eventName, properties, options)
```

### Parameters

| Parameter    | Type   | Required | Description       |
| ------------ | ------ | -------- | ----------------- |
| `eventName`  | string | Yes      | Name of the event |
| `properties` | object | No       | Event properties  |
| `options`    | object | No       | Tracking options  |

### Options

| Option      | Type     | Description                   |
| ----------- | -------- | ----------------------------- |
| `success`   | function | Called when event is accepted |
| `error`     | function | Called on tracking error      |
| `useBeacon` | boolean  | Force Beacon API usage        |

### Return Value

Returns a Promise that resolves with the event object:

```javascript theme={"dark"}
permutive.track('MyEvent', { data: 'value' })
  .then(function(event) {
    console.log('Tracked:', event);
  })
  .catch(function(error) {
    console.error('Error:', error);
  });
```

## Event Examples

<Tabs>
  <Tab title="E-commerce">
    ```javascript theme={"dark"}
    // Product view
    permutive.track('ProductView', {
      product_id: 'SKU123',
      product_name: 'Blue Widget',
      category: 'Widgets',
      price: 29.99,
      currency: 'USD'
    });

    // Add to cart
    permutive.track('AddToCart', {
      product_id: 'SKU123',
      quantity: 2,
      cart_value: 59.98
    });

    // Purchase
    permutive.track('Purchase', {
      order_id: 'ORDER-456',
      products: [
        { id: 'SKU123', quantity: 2 }
      ],
      total: 59.98,
      currency: 'USD',
      payment_method: 'credit_card'
    });
    ```
  </Tab>

  <Tab title="User Actions">
    ```javascript theme={"dark"}
    // Login
    permutive.track('Login', {
      method: 'email',
      is_new_session: true
    });

    // Registration
    permutive.track('Registration', {
      signup_source: 'homepage_banner',
      plan_type: 'premium'
    });

    // Search
    permutive.track('Search', {
      query: 'blue widgets',
      results_count: 42
    });

    // Share
    permutive.track('Share', {
      content_type: 'article',
      content_id: 'article-123',
      platform: 'twitter'
    });
    ```
  </Tab>

  <Tab title="Engagement">
    ```javascript theme={"dark"}
    // Button click
    permutive.track('ButtonClick', {
      button_id: 'cta-signup',
      button_text: 'Start Free Trial',
      page_section: 'hero'
    });

    // Tab switch
    permutive.track('TabSwitch', {
      from_tab: 'overview',
      to_tab: 'pricing'
    });

    // Modal view
    permutive.track('ModalView', {
      modal_name: 'newsletter-popup',
      trigger: 'exit_intent'
    });
    ```
  </Tab>

  <Tab title="Subscription">
    ```javascript theme={"dark"}
    // Subscription start
    permutive.track('SubscriptionStart', {
      plan_id: 'premium-monthly',
      plan_name: 'Premium',
      price: 9.99,
      billing_period: 'monthly'
    });

    // Paywall hit
    permutive.track('PaywallHit', {
      paywall_type: 'hard',
      article_id: 'article-123',
      articles_read: 5
    });

    // Trial started
    permutive.track('TrialStarted', {
      trial_length_days: 14,
      plan_type: 'premium'
    });
    ```
  </Tab>
</Tabs>

## Event Listeners

### on() - Persistent Listener

Listen for all occurrences of an event:

```javascript theme={"dark"}
// Listen for all Pageview events
permutive.on('Pageview', function(event, error) {
  if (error) {
    console.error('Event error:', error);
    return;
  }
  console.log('Pageview tracked:', event);
});

// Listen for custom events
permutive.on('Purchase', function(event) {
  analytics.trackRevenue(event.properties.total);
});
```

### once() - Single Listener

Listen for only the first occurrence:

```javascript theme={"dark"}
// Listen for first Pageview only
permutive.once('Pageview', function(event) {
  console.log('First pageview:', event);
});

// Wait for SDK ready event
permutive.once('permutive:ready', function() {
  console.log('SDK is ready');
});
```

### Pattern Matching

Use regex to match multiple event types:

```javascript theme={"dark"}
// Listen for all events starting with "Video"
permutive.on(/^Video/, function(event) {
  console.log('Video event:', event.name, event);
});

// Listen for all Purchase-related events
permutive.on(/Purchase|AddToCart|Checkout/, function(event) {
  console.log('E-commerce event:', event.name);
});
```

### Removing Listeners

Store the listener reference to remove later:

```javascript theme={"dark"}
var listener = permutive.on('Pageview', function(event) {
  console.log('Pageview:', event);
});

// Later, remove the listener
listener.remove();
```

## Standard Event Types

The SDK defines these standard event types:

| Event                | Description               |
| -------------------- | ------------------------- |
| `Pageview`           | Page load (via web addon) |
| `PageviewEngagement` | User engagement signals   |
| `PageviewComplete`   | User leaves page          |
| `FormSubmission`     | Form submitted            |
| `LinkClick`          | Link clicked              |
| `Videoview`          | Video playback started    |
| `VideoEngagement`    | Video engagement signals  |
| `VideoCompletion`    | Video completed           |
| `SegmentEntry`       | User entered a cohort     |
| `SegmentExit`        | User exited a cohort      |

<Info>
  Standard events (Pageview, etc.) are tracked automatically by the web addon. Use `track()` for custom events.
</Info>

## SDK Events

Listen for internal SDK events:

```javascript theme={"dark"}
// SDK ready
permutive.on('permutive:ready', function() {
  console.log('SDK initialized');
});

// Realtime data ready
permutive.on('permutive:realtime', function() {
  console.log('Realtime cohort data available');
});

// SDK reset
permutive.on('permutive:reset', function() {
  console.log('SDK state was reset');
});

// Web addon ready
permutive.on('permutive:web:ready', function() {
  console.log('Web addon initialized');
});
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use Descriptive Event Names">
    ```javascript theme={"dark"}
    // Good - clear, specific names
    permutive.track('ArticleRead', {...});
    permutive.track('NewsletterSignup', {...});
    permutive.track('PremiumTrialStarted', {...});

    // Avoid - vague or generic names
    permutive.track('Click', {...});
    permutive.track('Event', {...});
    permutive.track('Action', {...});
    ```
  </Accordion>

  <Accordion title="Include Relevant Properties">
    ```javascript theme={"dark"}
    // Good - actionable properties
    permutive.track('Purchase', {
      order_id: 'ORDER-123',
      total: 99.99,
      currency: 'USD',
      product_count: 3,
      coupon_used: true
    });

    // Avoid - too few or irrelevant properties
    permutive.track('Purchase', {
      timestamp: Date.now()  // Already captured automatically
    });
    ```
  </Accordion>

  <Accordion title="Track at the Right Time">
    ```javascript theme={"dark"}
    // Good - track when action completes
    function onPurchaseComplete(order) {
      permutive.track('Purchase', {
        order_id: order.id,
        total: order.total
      });
    }

    // Avoid - tracking before action completes
    function onCheckoutClick() {
      permutive.track('Purchase', {...});  // Purchase hasn't happened yet!
      processPayment();
    }
    ```
  </Accordion>

  <Accordion title="Don't Over-Track">
    Track meaningful user actions, not every interaction:

    ```javascript theme={"dark"}
    // Good - meaningful actions
    permutive.track('AddToCart', {...});
    permutive.track('Search', {...});

    // Avoid - excessive tracking
    permutive.track('MouseMove', {...});
    permutive.track('Scroll', {...});
    permutive.track('Focus', {...});
    ```
  </Accordion>

  <Accordion title="Handle Errors">
    ```javascript theme={"dark"}
    permutive.track('ImportantEvent', properties, {
      success: function(event) {
        // Event tracked successfully
      },
      error: function(type, msg) {
        // Log or handle error
        errorLogger.log('Permutive tracking failed', type, msg);
      }
    });
    ```
  </Accordion>
</AccordionGroup>

## Tracking on Page Unload

For events that must be tracked when the user leaves:

```javascript theme={"dark"}
// Use Beacon API for reliable delivery
window.addEventListener('beforeunload', function() {
  permutive.track('PageExit', {
    time_on_page: calculateTimeOnPage()
  }, {
    useBeacon: true
  });
});
```

<Info>
  The web addon automatically tracks `PageviewComplete` on page unload, so you don't need to track basic exit events manually.
</Info>

## Debugging

Enable debug mode to see all tracked events:

```
?__permutive.loggingEnabled=true
```

Console output:

```
[Permutive] Tracking: Purchase {order_id: "123", total: 99.99}
[Permutive] Event accepted: 1/1
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Events not appearing in dashboard">
    **Problem:** `track()` called but no events in dashboard.

    **Solutions:**

    * Check consent is granted (if `consentRequired: true`)
    * Verify SDK is initialized
    * Enable debug mode to see if events are accepted
    * Check for JavaScript errors before track call
    * Allow processing time (events may take minutes to appear)
  </Accordion>

  <Accordion title="Callback not firing">
    **Problem:** Success/error callbacks not called.

    **Solutions:**

    * Verify callback functions are defined correctly
    * Check for errors in callback code
    * Ensure SDK is loaded before tracking
  </Accordion>

  <Accordion title="Properties missing from event">
    **Problem:** Event tracked but some properties missing.

    **Solutions:**

    * Check property names match expected schema
    * Verify property types are correct
    * Look for undefined values being passed
    * Check for typos in property names
  </Accordion>
</AccordionGroup>

## Related Documentation

<CardGroup cols={2}>
  <Card title="Event Properties" icon="list" href="/sdks/web/javascript-sdk/core-concepts/event-properties">
    Structure event data
  </Card>

  <Card title="Pageview Tracking" icon="file" href="/sdks/web/javascript-sdk/features/pageview-tracking">
    Automatic pageview tracking
  </Card>

  <Card title="Cohorts" icon="users" href="/sdks/web/javascript-sdk/core-concepts/cohorts-and-activations">
    Events power cohort membership
  </Card>

  <Card title="Connectivity Events" icon="plug" href="/products/connectivity/events">
    Event schema documentation
  </Card>
</CardGroup>
