# How analytics works on the Arc Audio Player

Source: https://dev.arcxp.com/audio-center/developer-docs/audio-player-analytics/

Walkthrough of how analytics works on the Arc Audio Player

This guide explains how analytics work in the `<arc-audio-player>` and `<arc-card-audio-player>` web components, what the player captures automatically, and how a publisher embedding the player can track user plays and clicks themselves.

Two layers apply here:

1. Playback quality telemetry, which the player collects automatically and reports to Arc XP for service monitoring. Enabled by default per player instance; you can opt out.
2. Product analytics (your tool of choice), which you wire yourself. The library exposes the events you need so you can forward them to GA, Segment, Adobe, Amplitude, or anything else.

---

## 1\. Built-in playback telemetry (QoE)

The player automatically collects playback quality-of-experience telemetry and reports it to Arc XP for platform-wide playback-health monitoring. Collection runs through Mux, a third-party `QoE` service, under Arc XP’s account: you have nothing to set up, and the data never reaches any analytics account of yours.

### When it runs

Telemetry starts automatically when the player loads a clip by `media-id` (this also requires `org-id`):

```html
<arc-audio-player
  org-id="your-org-id"
  media-id="some-media-id"
  env="prod"
></arc-audio-player>
```

Direct-stream playback (the `stream` attribute instead of `media-id`) sends no telemetry.

### What the player collects

- Views and play starts
- Pause, seek (seeking / seeked), resume
- Completion (ended)
- Rebuffering count and duration
- Startup time, time to first frame
- Playback errors
- Device, browser, operating system, connection metadata

### Turn off telemetry

To turn the built-in telemetry off, add the `disable-default-analytics` attribute (or set `disableDefaultAnalytics: true` inside `config`; the config value wins over the attribute when both exist). Turn it off for consent or data-processing reasons, or because you already run a separate analytics setup:

```html
<arc-audio-player org-id="your-org-id" media-id="some-media-id" disable-default-analytics></arc-audio-player>
```

Opting out only disables the telemetry. The `arc-player-*` events that follow still fire, so you can turn off the built-in reporting and run separate analytics on those events.

### Telemetry scope

This telemetry reports playback service health: errors, buffering, and startup performance. To measure engagement (clicks, click-driven versus autoplay-driven plays, funnels, sign-ups, or attribution), wire the player’s events into a separate tool by using the patterns later in this guide.

---

## 2\. Tracking playback yourself

> **Event naming:**
> 
> The player’s events use the `arc-player-*` naming: `arc-player-ready`, `arc-player-error`, and the playback events shown next.

### Prefer the built-in playback events

The library already emits high-level playback events on the player element (bubbling), so in most cases you do not need the manual `timeupdate` math in the next section:

- `arc-player-playback-started`: fires once when playback actually begins.
- `arc-player-playback-progress`: fires once per **watched** quartile, with `detail.quartile` \= `25` | `50` | `75` (the player ignores seeks, so scrubbing does not false-fire).
- `arc-player-playback-completed`: fires on completion.

Each event’s `detail` includes the `player` instance and a `context` snapshot. They bubble, so one `document`\-level listener covers every player on the page:

```js
document.addEventListener('arc-player-playback-started', (e) => {
  myAnalytics.track('audio_play', { mediaId: e.detail.player.getAttribute('media-id') });
});
```

Reach for the manual approach below only when you need custom thresholds.

### Manual tracking with native media events

The library dispatches a `arc-player-ready` event on `document` after the player mounts. Its `detail.player` holds the custom-element instance, which exposes `mediaElement` (the underlying `<audio>` element) through a getter.

Native HTML5 media events offer another way to track reproductions:

```html
<arc-audio-player org-id="..." media-id="..."></arc-audio-player>

<script>
  document.addEventListener('arc-player-ready', (e) => {
    const player = e.detail.player;
    const audio  = player.mediaElement;
    const id     = player.getAttribute('media-id');

    audio.addEventListener('play',  () => myAnalytics.track('audio_play',     { mediaId: id }));
    audio.addEventListener('pause', () => myAnalytics.track('audio_pause',    { mediaId: id, t: audio.currentTime }));
    audio.addEventListener('ended', () => myAnalytics.track('audio_complete', { mediaId: id }));

    // Quartile progress
    const fired = new Set();
    audio.addEventListener('timeupdate', () => {
      if (!audio.duration) return;
      const pct = (audio.currentTime / audio.duration) * 100;
      [25, 50, 75].forEach((q) => {
        if (pct >= q && !fired.has(q)) {
          fired.add(q);
          myAnalytics.track('audio_progress', { mediaId: id, quartile: q });
        }
      });
    });
  });
</script>
```

Replace `myAnalytics.track(...)` with your provider’s call (`gtag`, `analytics.track`, `window.adobeDataLayer.push`, and so on).

---

## 3\. Tracking clicks

| Click scope                                                                    | How to hook it                                                                                                                                                                                                                                                        |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Play / pause button** (distinguish user click from autoplay / scripted play) | Reach into the player’s open shadow root: player.shadowRoot.querySelector('media-play-button') and add a pointerdown listener. The native play event alone cannot tell you whether the user clicked.                                                                  |
| **Other control-bar buttons** (volume, mute, fullscreen)                       | Same shadow-root pattern: query the media-chrome custom elements (media-mute-button, media-volume-range, …) inside player.shadowRoot and attach click/change listeners. This approach pierces the shadow DOM, so internal markup can change between library versions. |
| **Player-container clicks** (a click that lands on the host element)           | Listen on the host element itself: player.addEventListener('click', …). Clicks on shadow internals retarget to the host, so this catches generic clicks without piercing the shadow DOM.                                                                              |

### Worked example: distinguishing user-driven play from autoplay

```js
document.addEventListener('arc-player-ready', (e) => {
  const player    = e.detail.player;
  const audio     = player.mediaElement;
  const playBtn   = player.shadowRoot.querySelector('media-play-button');
  let userClicked = false;

  if (playBtn) {
    playBtn.addEventListener('pointerdown', () => { userClicked = true; });
  }

  audio.addEventListener('play', () => {
    myAnalytics.track('audio_play', {
      mediaId:  player.getAttribute('media-id'),
      source:   userClicked ? 'user_click' : 'programmatic',
    });
    userClicked = false;
  });
});
```

---

## 4\. Wiring to a specific vendor

The player stays vendor-neutral for product analytics: any SDK works. The following example uses Google Analytics 4:

```js
document.addEventListener('arc-player-ready', (e) => {
  const player = e.detail.player;
  const audio  = player.mediaElement;
  const id     = player.getAttribute('media-id');

  audio.addEventListener('play',  () => gtag('event', 'audio_play',     { media_id: id }));
  audio.addEventListener('ended', () => gtag('event', 'audio_complete', { media_id: id }));
});
```

Swap `gtag(...)` for Segment’s `analytics.track(...)`, Adobe’s `_satellite.track(...)`, Amplitude’s `amplitude.track(...)`, and so on.

---

## Reference: available events and properties

All event names use the standard `arc-player-*` form.

| Name                          | Where                                                    | What you get                                                                  |
| ----------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------- |
| arc-player-ready              | Dispatched once per player (on the element and document) | detail.player, the custom-element instance                                    |
| arc-player-error              | Dispatched if the player fails to initialize             | detail.player, detail.error                                                   |
| arc-player-playback-started   | Dispatched on the player element when playback begins    | detail.player, detail.context                                                 |
| arc-player-playback-progress  | Dispatched once per watched quartile                     | detail.quartile (25/50/75), detail.player, detail.context                     |
| arc-player-playback-completed | Dispatched on completion                                 | detail.player, detail.context                                                 |
| player.mediaElement           | Getter on the audio player                               | The underlying <audio> element; use it to listen to native HTML5 media events |
| player.shadowRoot             | Open mode, direct access                                 | Media-chrome control elements (use for click tracking)                        |
