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

# Events, fields & React hooks

> Event fields per event_name, React hooks, and which events work on the server

Install, init, and walkthrough examples live in [Overview & setup](/sdks/analytics/overview). **This page** is the reference for `trackEvent`, every `event_name`, and React hooks.

<h2 id="trackEvent">
  Tracking events
</h2>

`trackEvent` sends one event or up to 50 in a single call. Which fields you can include depends on `event_name`.

```typescript theme={null}
const result = await analytics.trackEvent(input)
// input: one event or a list of events
```

<ParamField path="input" type="event | list of events" required>
  A single event, or a list of up to 50 events in one call. An empty list returns immediately with
  `accepted: 0` and does not contact the API.
</ParamField>

### Shared fields

Optional on **every** event below — you do not repeat them in each accordion. Use them when a screen
or milestone should appear as a funnel step in reporting.

<ParamField body="is_funnel_step" type="boolean">
  When `true`, marks this event as a funnel step. Omit or leave false for ordinary page views or
  minor events.
</ParamField>

<ParamField body="funnel_step_label" type="string">
  Human-readable step name in dashboards (max 128 characters). Meaningful when `is_funnel_step` is
  true — e.g. `"Shipping"` or `"Payment"`.
</ParamField>

<h3 id="events">
  Events
</h3>

Expand an event for an example and field details. **React** is the `analytics()` module factory and the
track hooks. **JavaScript** lists every event you can send from `initAnalytics`. **Server** lists events
you can send from `initAnalyticsServer` — shared event names are documented in both tabs.

<Tabs>
  <Tab title="React">
    <span id="react-hooks" />

    <AccordionGroup>
      <Accordion title="analytics()" description="Module factory for EmbeddablesProvider — not a hook">
        ```typescript theme={null}
        import { EmbeddablesProvider } from '@embeddables/core/react'
        import { analytics } from '@embeddables/analytics/react'

        <EmbeddablesProvider config={config} modules={[analytics({ publishableKey })]}>
          {children}
        </EmbeddablesProvider>
        ```

        Registers Analytics on the provider's `modules` prop. `core` comes from the provider — do not pass
        it here. The generated CLI setup wires this for you.

        <ParamField body="publishableKey" type="string">
          Optional. Overrides `publishableKey` on Core config when Analytics must own the key.
        </ParamField>
      </Accordion>

      <Accordion title="useTrackEvent()" description="Track any event from React">
        <ResponseField name="trackEvent" type="function">
          Same inputs as [trackEvent](#trackEvent) above. Does nothing without error if Analytics is not
          ready yet.
        </ResponseField>

        <ResponseField name="isPending" type="boolean">
          `true` while a send is in progress — not while Analytics is still loading.
        </ResponseField>

        <ResponseField name="isError" type="boolean">
          `true` when the latest track call failed.
        </ResponseField>

        <ResponseField name="error" type="unknown">
          Details from the failed send, when `isError` is true.
        </ResponseField>
      </Accordion>

      <Accordion title="useTrackClickEvent()" description="Wrapper for button:clicked">
        <ParamField path="key" type="string" required>
          Passed through as `button_key` — see [button:clicked](#events) under **JavaScript**.
        </ParamField>

        <ParamField path="callback" type="function">
          Optional. Runs only after a successful track.
        </ParamField>

        Returns an object with `trackClickEvent`, `isPending`, `isError`, and `error`. Calling
        `trackClickEvent` with `key` and optional `callback` returns an `onClick` handler.
      </Accordion>

      <Accordion title="useTrackCustomEvent()" description="Wrapper for custom_event:triggered">
        Returns `trackCustomEvent`, `isPending`, `isError`, and `error`. Optional `properties` follow
        [custom\_event:triggered](#events) under **JavaScript** or **Server**.
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="JavaScript">
    <AccordionGroup>
      <Accordion title="page:viewed" description="A screen or route was shown">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'page:viewed',
          page_key: 'checkout',
          is_funnel_step: true,
          funnel_step_label: 'Checkout',
        })
        ```

        <ParamField body="page_key" type="string" required>
          Identifier for the page or step in your project (1–128 characters). Not the same as a form id.
        </ParamField>

        **Optional browser context** — added automatically when you leave these fields out. Analytics reads
        them once when you call `initAnalytics` (from the page URL and browser); values you set on the event
        override what was saved at setup.

        | Field          | Type   | Where it comes from                                                           |
        | -------------- | ------ | ----------------------------------------------------------------------------- |
        | `utm_source`   | string | `utm_source` URL parameter                                                    |
        | `utm_medium`   | string | `utm_medium` URL parameter                                                    |
        | `utm_campaign` | string | `utm_campaign` URL parameter                                                  |
        | `utm_content`  | string | `utm_content` URL parameter                                                   |
        | `utm_term`     | string | `utm_term` URL parameter                                                      |
        | `utm_id`       | string | `utm_id` URL parameter                                                        |
        | `device`       | string | Device type (`mobile`, `tablet`, or `desktop`)                                |
        | `country`      | string | Country guess from the browser; the API may also infer country from the visit |
      </Accordion>

      <Accordion title="button:clicked" description="A button or CTA was pressed">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'button:clicked',
          button_key: 'buy_now',
        })
        ```

        <ParamField body="button_key" type="string" required>
          A stable name for this button in analytics (1–128 characters) — use the same `key` as in
          `trackClickEvent({ key: … })` or in `trackEvent({ event_name: 'button:clicked', button_key: …
                              })`.
        </ParamField>
      </Accordion>

      <Accordion title="form:submitted" description="A form was submitted">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'form:submitted',
          form_key: 'intake',
        })
        ```

        Answers are sent as separate `data:updated` / `field:updated` events, not on this event.

        <ParamField body="form_key" type="string" required>
          Identifier for the form (1–128 characters), matching the form id from your Embeddables setup
          (same as in [Forms](/sdks/forms/reference#analytics-events)).
        </ParamField>
      </Accordion>

      <Accordion title="payment:completed" description="A purchase or payment finished">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'payment:completed',
          payment_value: 49,
          is_funnel_step: true,
          funnel_step_label: 'Purchase',
        })
        ```

        <ParamField body="payment_value" type="number" required>
          Numeric amount for the completed payment.
        </ParamField>
      </Accordion>

      <Accordion title="custom_event:triggered" description="Custom moment with optional properties">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'custom_event:triggered',
          properties: { promo: 'summer_sale' },
        })
        ```

        <ParamField body="properties" type="object">
          Optional extra details — labels and values you choose. Each key may be up to 128 characters.
        </ParamField>
      </Accordion>

      <Accordion title="field:updated" description="One form field value changed">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'field:updated',
          field_key: 'email',
          field_type: 'email',
          field_value: 'user@example.com',
        })
        ```

        Sent automatically by [Forms](/sdks/forms/reference#analytics-events) only when Analytics is wired
        to Forms — otherwise call `trackEvent` yourself.

        <ParamField body="field_key" type="string" required>
          Identifier for the form field (1–128 characters), matching the field id in your [Forms](/sdks/forms/reference#analytics-events)
          setup.
        </ParamField>

        <ParamField body="field_type" type="string" required>
          Kind of field: `text`, `email`, `number`, `boolean`, `select`, `multiselect`, or `json`.
        </ParamField>

        <ParamField body="field_value" type="string | number | boolean | object | array">
          Optional answer — text, number, yes/no, list of choices (`multiselect`), or structured data
          (`json`).
        </ParamField>

        <ParamField body="registry_field_id" type="string">
          Optional. Advanced: id when the field is linked to the Field Registry.
        </ParamField>

        <ParamField body="protocol_field_id" type="string">
          Optional. Advanced: id when the field is tied to a protocol form question.
        </ParamField>
      </Accordion>

      <Accordion title="data:updated" description="Several form answers changed at once">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'data:updated',
          data: {
            plan: { value: 'pro', label: 'Pro plan' },
          },
        })
        ```

        Only the fields that changed — not the entire form. Sent automatically by Forms only when Analytics
        is wired to Forms — otherwise call `trackEvent` yourself.

        <ParamField body="data" type="object" required>
          Each key is a field id; each value has `value` (answer text, max 1024 characters) and
          `label` (display name, max 256 characters).
        </ParamField>
      </Accordion>

      <Accordion title="experiment:assigned" description="Visitor assigned to an A/B test variant">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'experiment:assigned',
          experiment_key: 'hero_test',
          variant: 'control',
        })
        ```

        Sent automatically by [Experiments](/sdks/experiments/reference#analytics-events) only when Analytics
        is wired to Experiments and a **new** assignment is made — otherwise call `trackEvent` yourself.

        <ParamField body="experiment_key" type="string" required>
          Experiment identifier (1–128 characters).
        </ParamField>

        <ParamField body="variant" type="string" required>
          Assigned variant name (1–128 characters).
        </ParamField>
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Server">
    <span id="server" />

    <AccordionGroup>
      <Accordion title="custom_event:triggered" description="Custom moment with optional properties">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'custom_event:triggered',
          properties: { promo: 'summer_sale' },
        })
        ```

        <ParamField body="properties" type="object">
          Optional extra details — labels and values you choose. Each key may be up to 128 characters.
        </ParamField>
      </Accordion>

      <Accordion title="field:updated" description="One form field value changed">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'field:updated',
          field_key: 'email',
          field_type: 'email',
          field_value: 'user@example.com',
        })
        ```

        Sent automatically by [Forms](/sdks/forms/reference#analytics-events) only when Analytics is wired
        to Forms — otherwise call `trackEvent` yourself.

        <ParamField body="field_key" type="string" required>
          Identifier for the form field (1–128 characters), matching the field id in your [Forms](/sdks/forms/reference#analytics-events)
          setup.
        </ParamField>

        <ParamField body="field_type" type="string" required>
          Kind of field: `text`, `email`, `number`, `boolean`, `select`, `multiselect`, or `json`.
        </ParamField>

        <ParamField body="field_value" type="string | number | boolean | object | array">
          Optional answer — text, number, yes/no, list of choices (`multiselect`), or structured data
          (`json`).
        </ParamField>

        <ParamField body="registry_field_id" type="string">
          Optional. Advanced: id when the field is linked to the Field Registry.
        </ParamField>

        <ParamField body="protocol_field_id" type="string">
          Optional. Advanced: id when the field is tied to a protocol form question.
        </ParamField>
      </Accordion>

      <Accordion title="data:updated" description="Several form answers changed at once">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'data:updated',
          data: {
            plan: { value: 'pro', label: 'Pro plan' },
          },
        })
        ```

        Only the fields that changed — not the entire form. Sent automatically by Forms only when Analytics
        is wired to Forms — otherwise call `trackEvent` yourself.

        <ParamField body="data" type="object" required>
          Each key is a field id; each value has `value` (answer text, max 1024 characters) and
          `label` (display name, max 256 characters).
        </ParamField>
      </Accordion>

      <Accordion title="experiment:assigned" description="Visitor assigned to an A/B test variant">
        ```typescript theme={null}
        await analytics.trackEvent({
          event_name: 'experiment:assigned',
          experiment_key: 'hero_test',
          variant: 'control',
        })
        ```

        Sent automatically by [Experiments](/sdks/experiments/reference#analytics-events) only when Analytics
        is wired to Experiments and a **new** assignment is made — otherwise call `trackEvent` yourself.

        <ParamField body="experiment_key" type="string" required>
          Experiment identifier (1–128 characters).
        </ParamField>

        <ParamField body="variant" type="string" required>
          Assigned variant name (1–128 characters).
        </ParamField>
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

<Note>
  React hooks do not send events during server-side page rendering — use `initAnalyticsServer` in
  [Overview & setup](/sdks/analytics/overview) instead. For visitor or project id in React, use
  Core's `useAppUserId` and `useEmbeddablesProjectId`.
</Note>

### Returns

<ResponseField name="app_user_id" type="string" required>
  Visitor id for this call. Created by the API the first time if Core did not have one yet; save it
  in Core for later events.
</ResponseField>

<ResponseField name="accepted" type="number" required>
  How many events in the call were accepted (0–50).
</ResponseField>

<ResponseField name="forwarded" type="boolean" required>
  Whether the events were passed on to reporting storage. Can be `false` even when the call succeeds
  if reporting is not set up or temporarily unavailable.
</ResponseField>

```json theme={null}
{
  "app_user_id": "usr_abc123",
  "accepted": 1,
  "forwarded": true
}
```
