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

# Track Events

> Send application events from Confidence SDKs, set up the event schema, and verify that events arrive.

Events are the main way to record data for [Confidence Cloud](/docs/start/confidence-cloud).
An event records something that a user does or that happens in your product, such as a page view,
a purchase, or a crash. Confidence uses events to back fact tables and metrics for your experiments.

Event tracking has two parts:

1. **Send events to Confidence.** Your application calls `track` on a Confidence SDK.
2. **Set up an event schema.** Confidence stores an event only when an event definition with a
   matching name and schema exists.

You can define the schema in advance, or send events first and then review and create the event
from the detected schema. After you create the event, Confidence records the events.

<Note>
  Application events are different from [apply events](/docs/reference/sdks/apply-event). SDKs send
  apply events automatically when your application uses a flag. You send application events explicitly
  with `track`.
</Note>

## SDK Support

| SDK | `track` support | Call |
| - | - | - |
| [JavaScript (Web)](/docs/reference/sdks/client/javascript) | Yes | OpenFeature `client.track(name, details)` or `confidence.track(name, data)` |
| [iOS (Swift)](/docs/reference/sdks/client/ios) | Yes | OpenFeature `client.track(key:)` |
| [Android (Kotlin)](/docs/reference/sdks/client/android) | Yes | OpenFeature `client.track(name)` |
| [Flutter](/docs/reference/sdks/client/flutter) | Yes | `confidence.track(name, data)` |
| [Unity](/docs/reference/sdks/client/unity) | Yes | `client.Track(name, details)` |
| [.NET (client)](/docs/reference/sdks/client/dotnet) | Yes | `await client.TrackAsync(name, data)` |
| [.NET (server)](/docs/reference/sdks/server/dotnet) | Yes | `await client.TrackAsync(name, data)` |
| [Go](/docs/reference/sdks/server/go) | Yes | Go SDK `confidence.Track(ctx, name, data)` or local-resolve OpenFeature provider `client.Track(...)` |
| [Java](/docs/reference/sdks/server/java) | Yes | Java SDK `confidence.track(name, data)` or local-resolve OpenFeature provider `client.track(...)` |
| [JavaScript (server)](/docs/reference/sdks/server/javascript) and [Next.js](/docs/reference/sdks/server/nextjs) | Yes | OpenFeature server provider or local-resolve provider `client.track(name, context, details)` |
| [Python](/docs/reference/sdks/server/python) | Yes | Python SDK `confidence.track(name, data)` or local-resolve OpenFeature provider `client.track(...)` |
| [Rust](/docs/reference/sdks/server/rust) | Rust SDK only | `EventSender::track(name, message)`. The Rust local-resolve provider resolves flags only. |
| [Ruby](/docs/reference/sdks/server/ruby) | Yes | Local-resolve provider `provider.track(name, ...)` or `provider.track!(name, ...)` |
| [PHP](/docs/reference/sdks/server/php) | No | The PHP provider resolves flags only. |
| [Cloudflare](/docs/reference/sdks/edge/cloudflare) | Yes | The resolver accepts `POST /v1/events:publish` and forwards events to Confidence in batches. |
| [Fastly](/docs/reference/sdks/edge/fastly) | In development | |

Events authenticate with the same [client credentials](/docs/capabilities/flags/clients) that the SDK
uses to resolve flags.

## JavaScript (Web)

### OpenFeature Provider

The Confidence OpenFeature provider for web browsers implements the
[OpenFeature tracking API](https://openfeature.dev/specification/sections/tracking/). Call `track` on
the same OpenFeature client that you use for flags.

<Info>
  Tracking in the web provider requires `@openfeature/web-sdk` 1.3.0 or later and
  `@spotify-confidence/openfeature-web-provider` 0.3.22 or later, with a matching version of the
  `@spotify-confidence/sdk` peer dependency.
</Info>

```javascript theme={null}
import { OpenFeature } from '@openfeature/web-sdk';
import { createConfidenceWebProvider } from '@spotify-confidence/openfeature-web-provider';

const provider = createConfidenceWebProvider({
  clientSecret: 'your-client-secret',
  region: 'eu', // or 'us'; omit to use the global endpoint
  timeout: 1000,
});

await OpenFeature.setContext({
  targetingKey: 'user-123',
  platform: 'web',
});
await OpenFeature.setProviderAndWait(provider);

const client = OpenFeature.getClient();

// Send an event named "checkout-completed"
client.track('checkout-completed', {
  value: 42.5,
  currency: 'SEK',
  item_count: 3,
});
```

### Confidence SDK: `track(name, data?)`

The `@spotify-confidence/sdk` package exposes `track` on any `Confidence` instance. The SDK appends
the context set on the instance to each event.

```typescript theme={null}
confidence.track('event_name', { 'message-detail1': 'something interesting' });
```

<Note>
  Confidence plans to retire the standalone `Confidence` class. For new integrations, use the
  OpenFeature provider.
</Note>

### Confidence SDK: `track(manager)`

Pass a tracking manager instead of an event name to track data automatically. The web SDK includes
these managers:

| Manager | What it does |
| - | - |
| `visitorIdentity()` | Adds a browser-specific `visitor_id` to the context of flag resolves and events. The SDK stores it in a cookie named `cnfdVisitorId`. Pass `{ domain: '.example.com' }` to share it across subdomains. |
| `pageViews()` | Tracks page views on `load`, `pushState`, `replaceState`, `popstate`, and `hashchange`. |
| `webVitals()` | Sends events with [web vitals](https://web.dev/articles/vitals) data. |

```typescript theme={null}
import { visitorIdentity, pageViews, webVitals } from '@spotify-confidence/sdk';

confidence.track(visitorIdentity());
confidence.track(pageViews());
confidence.track(webVitals());
```

### Event Payload

The web provider builds the payload from two sources:

* **Tracking details.** The object you pass to `track` becomes top-level fields in the payload.
* **Evaluation context.** The provider adds the current evaluation context under a `context` field.
  It renames `targetingKey` to `targeting_key` and converts `Date` values to ISO 8601 strings.

The OpenFeature example produces this payload:

```json theme={null}
{
  "context": {
    "targeting_key": "user-123",
    "platform": "web"
  },
  "value": 42.5,
  "currency": "SEK",
  "item_count": 3
}
```

The provider reserves `context` for the evaluation context and ignores a tracking detail named `context`.

### Batches and Delivery

`track` returns immediately and doesn't report whether Confidence accepted the event. The SDK queues
events in memory and sends them in batches.

* **Rejected events.** The SDK logs a warning and doesn't resend them.
* **Network errors, server errors, and HTTP 429.** The SDK retries the batch with increasing delays,
  from 5 seconds up to 5 minutes. It stops retrying 30 minutes after the first try and drops the batch.
* **Other request errors**, such as an invalid client secret. The SDK logs an error and drops the batch.
* **Page hidden.** The SDK tries to send up to 25 queued events with the browser `sendBeacon` API.

The queue exists only in memory. When the page closes, you lose events that haven't reached Confidence.

## Swift

```swift theme={null}
let client = OpenFeatureAPI.shared.getClient()

// Track a custom application event
client.track(key: "checkout")
```

See the [iOS SDK reference](/docs/reference/sdks/client/ios) for provider setup.

## Android (Kotlin)

```kotlin theme={null}
val client = OpenFeatureAPI.getClient()

// Track a custom application event
client.track("checkout")
```

See the [Android SDK reference](/docs/reference/sdks/client/android) for provider setup.

## Flutter

```dart theme={null}
final confidence = ConfidenceFlutterSdk();
await confidence.setup("your-client-secret");

// Track custom event
confidence.track("event-name", {});
```

See the [Flutter SDK reference](/docs/reference/sdks/client/flutter) for setup.

## Unity and .NET

```csharp theme={null}
// .NET
await client.TrackAsync("button-clicked", new Dictionary<string, object> { ["button"] = "buy" });

// Unity
client.Track("checkout_completed",
    TrackingEventDetails.Builder().SetValue(42.0).Set("currency", "SEK").Build());
```

## Go

```go theme={null}
// Go SDK
wg := confidence.Track(context.Background(), "checkout-complete", map[string]interface{}{"total": 49.99})

// Local-resolve OpenFeature provider
client.Track(ctx, "purchase", evalCtx, openfeature.NewTrackingEventDetails(49.99))
```

The Go SDK `Track` returns a `*sync.WaitGroup`.

## Java

```java theme={null}
// Java SDK
confidence.track("my-event", ConfidenceValue.of(Map.of("field", ConfidenceValue.of("data"))));

// Local-resolve OpenFeature provider
client.track("purchase", ctx, new MutableTrackingEventDetails(49.99f));
```

## JavaScript (Server)

```javascript theme={null}
// OpenFeature server provider or local-resolve provider
client.track('purchase', { targetingKey: 'user-123' }, { value: 49.99 });
```

## Python

```python theme={null}
# Python SDK
confidence.track("my-event", {"field": "data"})

# Local-resolve OpenFeature provider
client.track("purchase", context, TrackingEventDetails(value=49.99))
```

## Rust

```rust theme={null}
use confidence::event_sender::EventSender;

confidence.track("my-event", HashMap::from([
    ("field".to_string(), ConfidenceValue::String("data".into())),
]));
```

## Ruby

```ruby theme={null}
provider.track("checkout-completed",
  evaluation_context: OpenFeature::SDK::EvaluationContext.new(targeting_key: "user-1"))
```

The provider also has a `track!` method with the same parameters.

## Event Schema

An event definition names an event type and describes its payload with a schema. The event name in
`track` must match the event definition name. Event definition names use lowercase letters, digits,
and hyphens, and are 4 to 63 characters long, for example `checkout-completed`.

### Define the Schema in Advance

1. In the sidebar, select **Events** and click **Create**. The **Create event** dialog opens.
2. Enter the event name.
3. Edit the **Schema** to add fields. Set the field that identifies the user, such as
   `context.targeting_key`, to type String with semantic type Entity.

Every event needs at least one entity field. Without one, Confidence generates no fact table for
the event.

### Send Events First, Then Create the Event

1. Send the event from your application.
2. Confidence rejects events with no matching definition, detects a schema from the payload, and
   lists the event in the **Events** table as **Sent but not stored**.
3. In the event's row, click the outlined **Create**.
4. Review the schema. Set at least one String field to semantic type Entity.
5. Click **Create**.

Confidence stores events of this type from then on.

### Schema Changes

* **Fields missing from the schema.** Confidence drops fields that aren't in the schema and accepts the
  rest of the event. The event page shows a warning. Click **Update** in the warning to add
  the fields. Confidence doesn't recover values it dropped before the update.
* **Wrong field types.** Confidence rejects the event and counts it as a validation failure.
* **Type changes.** You can't change a field's name or type after you save it. Create a new event
  definition instead.

## Verify That Events Arrive

After your application starts sending an event:

* The **Events** page shows a status icon for each event type that indicates when the event last
  received data.
* The event page shows a **Usage** chart with hourly counts of published events and validation failures.
* A missing-fields warning on the event page means clients send fields that Confidence drops.
* Events with no definition appear as **Sent but not stored**.

These views show counts and status, not individual events. If you use your own warehouse, query the
tables that your [event connector](/docs/reference/api/how-to-guides/connectors/events) writes.

## Related Resources

<CardGroup cols={2}>
  <Card title="Fact Tables" href="/docs/capabilities/metrics/fact-tables">
    Turn event data into metric sources
  </Card>

  <Card title="Event Connectors" href="/docs/reference/api/how-to-guides/connectors/events">
    Export events to your own warehouse
  </Card>

  <Card title="Evaluation Context" href="/docs/reference/sdks/context">
    Configure the context that SDKs attach to events
  </Card>

  <Card title="Apply Events" href="/docs/reference/sdks/apply-event">
    Understand automatic flag assignment tracking
  </Card>
</CardGroup>
