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

# Event schema

> Learn about the structure of analytics events

## Overview

Analytics events are simple JSON objects that are emitted by the BeyondWords
Player. They contain information about user engagement. They are separate from
[player events](/docs-and-guides/distribution/player/sdk/javascript/player-events)
which contain information about the current state of the player.

Analytics events can be sent to three possible places:

1. The BeyondWords dashboard via our ingestion endpoint (metrics.beyondwords.io)

2. A custom analytics URL that you have configured (see [Analytics > Preferences](/docs-and-guides/analytics/preferences#send-data-to-custom-analytics-url)).

3. A Google Analytics account that you have configured (see [Analytics > Preferences](/docs-and-guides/analytics/preferences#send-data-to-custom-analytics-url)).

In all cases, the event schema is identical. You can inspect the events that
are sent by searching for metrics.beyondwords.io in the Network tab.

## Example event

```javascript Example event theme={null}
{
  "event_type": "play",
  "device_type": "desktop",
  "media_type": "content",
  "media_variant": "article"
  "project_id": 123,
  "content_id": "3f57001d-cb30-42c1-ad6f-047e813c360f",
  "source_id": "example-source-id",
  "analytics_id": 333,
  "ad_id": null,
  "media_id": 555,
  "media_format": "audio",
  "local_storage_id": "bef9218d-3871-450e-a7fa-5da65102f532",
  "listen_session_id": "839ff785-0cb8-4e74-a061-506f571c79ce",
  "session_created_at": 1672531200000,
  "duration": 123.45,
  "listen_length_seconds": 0.2,
  "listen_length_percent": 0.1620089105,
  "speed": 1,
  "segment_playback_enabled": true,
  "location": "https://example.com",
  "referrer": "https://example.com"
  "player_version": "1",
  "player_npm_version": "1.2.3",
}
```

## Event schema

<ParamField path="event_type" type="string">
  The type of analytics event. There are four types:

  * **load**: content loaded successfully and the media's duration is known
  * **play**: the media started playing for the current content item
  * **play\_progress**: playback reached the next 10% of the audio's duration
  * **ad\_link\_click**: the user clicked on the click-through URL for an advert
</ParamField>

<ParamField path="device_type" type="string">
  The type of device that emitted the event. There are three types:

  * **phone**: the width of the browser was between 0px and 499px
  * **tablet**: the width of the browser was between 500px and 999px
  * **desktop**: the width of the browser was 1000px or greater
  * **ios**: the event was sent from a native ios app (e.g. <a href="https://github.com/beyondwords-io/player-ios" target="_blank">player-ios</a>)
  * **android**: the event was sent from a native android app (e.g. <a href="https://github.com/beyondwords-io/player-android" target="_blank">player-android</a>)
</ParamField>

<ParamField path="media_type" type="string">
  The type of media loaded in the player. There are two types:

  * **content**: the event was emitted during content playback
  * **ad**: the event was emitted during advert playback
</ParamField>

<ParamField path="media_variant" type="string">
  The variant of media loaded in the player. There are two types:

  * **article**: the media is for the original article
  * **summary**: the media is for a summary of the article
</ParamField>

<ParamField path="project_id" type="integer | null">
  The numeric ID of the project whose content is loaded into the player.
  This field might be null if content wasn't fetched from the API and is instead set manually in the player.
</ParamField>

<ParamField path="content_id" type="string | integer | null">
  The string UUID or numeric ID of the content currently loaded into the player.
  This field might be null if content wasn't fetched from the API and is instead set manually in the player.
</ParamField>

<ParamField path="source_id" type="string | null">
  The string ID that can optionally be associated with the content currently loaded into the player.
  This field might be null if the source\_id ID wasn't set in the BeyondWords API.
</ParamField>

<ParamField path="analytics_id" type="integer | null">
  A numeric ID used by BeyondWords for associating this event with your project.
  This field might be null if content wasn't fetched from the API and is instead set manually in the player.
</ParamField>

<ParamField path="ad_id" type="integer | null">
  The numeric ID of the advert that is currently loaded into the player.
  This field is null when an advert isn't playing, i.e. when content is playing.
</ParamField>

<ParamField path="media_id" type="integer | null">
  The numeric ID of the content or advert media field that is currently loaded into the player.
  This field is null when VAST adverts are playing.
</ParamField>

<ParamField path="media_format" type="string">
  The format of media loaded in the player. There are two formats:

  * **audio**: the player is playing audio (or will play audio)
  * **video**: the player is playing video (or will play video)
</ParamField>

<ParamField path="local_storage_id" type="string | null">
  A string UUID associated with the current user and stored in local storage under the 'beyondwords' key.
  This field is null if advertConsent is set to 'without-local-storage'.
</ParamField>

<ParamField path="listen_session_id" type="string">
  A string UUID associated with the current player instance.
  This ID changes after the page is reloaded and is different for each player instance.
</ParamField>

<ParamField path="session_created_at" type="integer">
  The unix time in milliseconds at which the first analytics event was sent from the current player instance, as reported by the user's browser.
</ParamField>

<ParamField path="duration" type="float">
  The duration in seconds of the content or advert media currently loaded into the player.
</ParamField>

<ParamField path="listen_length_seconds" type="float">
  The duration in seconds that the user has listened to of the currently loaded media.
</ParamField>

<ParamField path="listen_length_percent" type="float">
  The percentage that the user has listened to of the currently loaded media.
</ParamField>

<ParamField path="speed" type="float">
  The speed at which the user is listening to the media, e.g. 0.5, 1 or 2.
</ParamField>

<ParamField path="segment_playback_enabled" type="boolean">
  Whether playback from segments is enabled, i.e. whether the clickableSections player setting is anything other than "none".
</ParamField>

<ParamField path="location" type="string">
  The value of window\.location.href when the event was emitted.
</ParamField>

<ParamField path="referrer" type="string">
  The value of document.referrer when the event was emitted.
</ParamField>

<ParamField path="player_version" type="string">
  This will always be the string "1" but we may use this later, e.g. to run A/B tests.
</ParamField>

<ParamField path="player_npm_version" type="string">
  The version of the NPM package as specified in the package.json file.
</ParamField>

## Sending your own events

If you are not using the BeyondWords player and have instead built your own
player, you can still send analytics to BeyondWords and we will aggregate them
and present them in the BeyondWords dashboard.

A **POST** request should be sent to `https://metrics.beyondwords.io` according to
the schema above. Please try to provide all fields so that events can be
aggregated and presented correctly to the user. However, if some fields are
missing, we will provide sensible defaults.

For example, `media_variant` will default to `"article"`, `media_format` will
default to `"audio"` and `device_type` will default to `'desktop"`. We recommend
you do not rely on these defaults if you are able to provide the data in the
unlikely event that the defaults change in the future.

Some fields may not be applicable (e.g. `player_npm_version`). In that case, it
is fine to leave the fields blank and they will be ignored. It may be helpful to
refer to the [player implementation](https://github.com/beyondwords-io/player/blob/main/src/helpers/sendToAnalytics.ts)
for more information about how a particular field is handled.

To test custom events, there may be a delay before they appear in the BeyondWords
dashboard. You may need to wait an hour or more for the events to appear.
If you are having trouble or are unsure what to set a field to, please contact
[support@beyondwords.io](mailto:support@beyondwords.io).
