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

# Events Overview

> Understand how DATALYR tracks and processes events

Events are actions that users take on your website or app. DATALYR captures these events to build complete customer journeys and attribute conversions to marketing campaigns.

## What is an Event

An event represents a single user action at a specific point in time. Every event includes:

**Event Name**
What happened (e.g., `page_view`, `purchase`, `button_clicked`)

**Timestamp**
When it happened (ISO 8601 format)

**User Identifier**
Who did it (visitor ID, user ID, or both)

**Properties**
Additional data about the event (e.g., product ID, price, page URL)

**Attribution Data**
Marketing source information (UTM parameters, click IDs, referrer)

## Event Structure

Every event DATALYR captures has this structure:

```json theme={null}
{
  "event_name": "purchase",
  "timestamp": "2025-09-29T10:30:45.123Z",
  "visitor_id": "anon_abc123...",
  "user_id": "user_456",
  "session_id": "sess_789",
  "properties": {
    "order_id": "ORDER_123",
    "revenue": 99.99,
    "currency": "USD",
    "items": [...]
  },
  "attribution": {
    "utm_source": "facebook",
    "utm_medium": "cpc",
    "utm_campaign": "summer_sale",
    "fbclid": "...",
    "source": "facebook",
    "medium": "cpc"
  },
  "device": {
    "user_agent": "...",
    "screen_width": 1920,
    "screen_height": 1080
  },
  "page": {
    "url": "https://example.com/checkout",
    "path": "/checkout",
    "referrer": "https://facebook.com"
  }
}
```

## Event Types

### Automatic Events

DATALYR automatically tracks these events without code:

**page\_view**
Fired when a user views a page. Captured automatically on every page load.

**session\_start**
Fired when a new session begins (first visit or after 30 minutes of inactivity).

**session\_end**
Fired when a session ends (user closes tab or 30 minutes of inactivity).

### Custom Events

Track specific user actions with custom events:

**Web:**

```javascript theme={null}
datalyr.track('button_clicked', {
  button_name: 'Sign Up',
  location: 'hero_section'
});
```

**iOS:**

```swift theme={null}
await DatalyrSDK.shared.track("Button Clicked", eventData: [
    "button_name": "Sign Up",
    "location": "hero_section"
])
```

**React Native:**

```typescript theme={null}
await Datalyr.track('button_clicked', {
  button_name: 'Sign Up',
  location: 'hero_section'
});
```

### Conversion Events

Special events that represent business goals:

**purchase**
User completes a purchase (e-commerce).

**signup**
User creates an account.

**lead**
User submits contact information.

**subscribe**
User subscribes to a service or newsletter.

**add\_to\_cart**
User adds item to shopping cart.

**begin\_checkout**
User starts checkout process.

## Event Properties

Properties add context to events. They can be anything relevant to the action:

### Standard Properties

**Revenue Events:**

* `revenue` or `amount`: Dollar amount
* `currency`: Three-letter code (USD, EUR, GBP)
* `order_id`: Unique order identifier
* `items`: Array of products purchased

**Product Events:**

* `product_id`: Product SKU or ID
* `product_name`: Product name
* `product_category`: Category or type
* `product_price`: Unit price
* `quantity`: Number of items

**Page Events:**

* `page_url`: Full page URL
* `page_path`: URL path only
* `page_title`: Document title
* `referrer`: Previous page URL

**User Events:**

* `email`: User email address
* `name`: User full name
* `user_id`: Internal user identifier
* `plan`: Subscription plan level

### Custom Properties

Add any properties relevant to your business:

```javascript theme={null}
datalyr.track('video_played', {
  video_title: 'Product Demo',
  video_duration: 120,
  video_category: 'tutorials',
  autoplay: false,
  video_provider: 'youtube'
});
```

**Best Practices:**

* Use snake\_case for property names
* Keep property names descriptive
* Use consistent naming across events
* Don't include sensitive data (passwords, SSNs)
* Limit to 50 properties per event

## Event Naming Conventions

Follow these conventions for consistent tracking:

### Use snake\_case

```javascript theme={null}
// Good
datalyr.track('button_clicked')
datalyr.track('form_submitted')

// Bad
datalyr.track('ButtonClicked')
datalyr.track('form-submitted')
```

### Use past tense

```javascript theme={null}
// Good
datalyr.track('purchase_completed')
datalyr.track('video_played')

// Bad
datalyr.track('purchase')
datalyr.track('play_video')
```

### Be specific

```javascript theme={null}
// Good
datalyr.track('checkout_started')
datalyr.track('newsletter_subscribed')

// Bad
datalyr.track('event')
datalyr.track('action')
```

### Standard Event Names

Use these standard names for common events:

**E-commerce:**

* `view_item`: User views product
* `add_to_cart`: Add item to cart
* `remove_from_cart`: Remove from cart
* `begin_checkout`: Start checkout
* `add_payment_info`: Enter payment details
* `purchase`: Complete purchase

**Engagement:**

* `button_clicked`: Any button click
* `link_clicked`: Link click
* `form_submitted`: Form submission
* `search`: Search query
* `share`: Content shared

**Content:**

* `video_played`: Video play
* `video_completed`: Video finished
* `download`: File download
* `scroll_depth`: Scroll milestone

## Event Priority

DATALYR processes events with different priorities:

### Critical Events (Highest Priority)

Sent immediately, bypass batching:

* `purchase`
* `signup`
* `subscribe`
* `lead`
* `conversion`

### High Priority Events

Sent in small batches (1-3 events):

* `add_to_cart`
* `begin_checkout`
* `view_item`
* `search`

### Standard Events

Batched for efficiency (up to 10 events):

* `page_view`
* `button_clicked`
* `scroll_depth`
* All other custom events

## Event Processing

### Client-Side Flow

1. **Event Captured**
   User action triggers event (page view, button click, etc.)

2. **Properties Collected**
   SDK gathers event properties, device info, page data

3. **Attribution Added**
   UTM parameters, click IDs, and computed source/medium attached

4. **Queued**
   Event added to batch queue (or sent immediately if critical)

5. **Sent to API**
   Batch sent to ingest endpoint via POST request

6. **Confirmed**
   Client receives 200 OK response

### Server-Side Processing

1. **Event Received**
   Ingest worker receives event batch

2. **Validated**
   Schema validation, workspace verification

3. **Enriched**
   Geo-IP data, device parsing, user agent parsing

4. **Attribution Computed**
   Attribution models applied (first-click, last-click, hybrid)

5. **Stored**
   Written to Tinybird data warehouse

6. **Indexed**
   Made available for queries and reports

## Event Deduplication

DATALYR automatically deduplicates events using:

**Event ID**
Unique identifier for each event (automatically generated or provided).

**Timestamp Window**
Events with same name, user, and timestamp within 1 second are deduplicated.

**Property Matching**
Events with identical properties within the time window are merged.

**Provide Event IDs for Server-Side Tracking:**

```javascript theme={null}
// Web
datalyr.track('purchase', {
  order_id: 'ORDER_123',
  revenue: 99.99
}, {
  event_id: 'evt_' + orderId // Prevent duplicates
});

// Server
await fetch('https://ingest.datalyr.com/events', {
  method: 'POST',
  body: JSON.stringify({
    workspaceId: 'ws_123',
    events: [{
      event_name: 'purchase',
      event_id: 'evt_ORDER_123', // Same ID = deduplicated
      properties: { ... }
    }]
  })
});
```

## Offline Events

Events are queued when offline and sent when connection restores:

**Automatic Queue**
Events saved to localStorage when offline.

**Auto-Retry**
Queue processed when online status detected.

**Max Queue Size**
100 events max (oldest dropped if exceeded).

**Manual Flush**

```javascript theme={null}
// Force send queued events
datalyr.flush();
```

## Event Validation

Events are validated before sending:

**Required Fields:**

* `event_name` (string, 1-255 chars)
* `timestamp` (ISO 8601 string or Unix milliseconds)
* `visitor_id` or `user_id` (at least one required)

**Property Limits:**

* Max 50 properties per event
* Property names: 255 chars max
* Property values: 10KB max
* Total event size: 50KB max

**Invalid events are dropped with error logged.**

## Next Steps

<CardGroup cols={2}>
  <Card title="Visitor Identification" icon="fingerprint" href="/understanding-data/visitor-identification">
    Learn how DATALYR identifies users
  </Card>

  <Card title="Identity Calls" icon="user" href="/understanding-data/identity-calls">
    Link users across devices
  </Card>

  <Card title="Properties and Metadata" icon="tags" href="/understanding-data/properties-and-metadata">
    Add context to events
  </Card>

  <Card title="Attribution Models" icon="chart-network" href="/understanding-data/attribution-models">
    How conversions are attributed
  </Card>
</CardGroup>

## Need Help?

Questions about events? Check our [troubleshooting guide](/troubleshooting/tracking-not-working) or contact support.
