> ## Documentation Index
> Fetch the complete documentation index at: https://social-b97141fb-auto-generate-llmstxt.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Livestream Analytics

> Track live and recorded room watch sessions with current SDK room analytics APIs.

Livestream analytics track a viewer's watch session for a room. The social.plus SDK owns session creation, local watch-session storage, duration updates, and pending-session sync. Your app owns deciding when a viewer is actually watching, when playback is paused or buffering, and when a viewer changes role from viewer to host or co-host.

<Note>
  This page covers SDK room watch-session APIs. Product analytics dashboards, custom event names, media player state, and business reporting are app-owned concerns after you create and update watch sessions.
</Note>

## Platform Surface

| Platform   | Analytics entry point                                    | Create session                   | Update duration                                    | Sync pending sessions        |
| ---------- | -------------------------------------------------------- | -------------------------------- | -------------------------------------------------- | ---------------------------- |
| TypeScript | `room.analytics()`                                       | `createWatchSession(startedAt)`  | `updateWatchSession(sessionId, duration, endedAt)` | `syncPendingWatchSessions()` |
| iOS        | `room.analytics()`                                       | `createWatchSession(startedAt:)` | `updateWatchSession(sessionId:duration:endedAt:)`  | `syncPendingWatchSessions()` |
| Android    | `room.analytics()`                                       | `createWatchSession(startedAt)`  | `updateWatchSession(sessionId, duration, endedAt)` | `syncPendingWatchSessions()` |
| Flutter    | No current public room analytics API found in this audit | Not available                    | Not available                                      | Not available                |

## Parameters

| Concept            | TypeScript             | iOS                  | Android                                            |
| ------------------ | ---------------------- | -------------------- | -------------------------------------------------- |
| Entry point        | `room.analytics()`     | `room.analytics()`   | `room.analytics()`                                 |
| Watchable statuses | `"live"`, `"recorded"` | `.live`, `.recorded` | `AmityRoomStatus.LIVE`, `AmityRoomStatus.RECORDED` |
| Start timestamp    | `Date`                 | `Date`               | `DateTime`                                         |
| Session ID         | `string`               | `String`             | `String`                                           |
| Duration           | `number` seconds       | `Int` seconds        | `Long` seconds                                     |
| End timestamp      | `Date`                 | `Date`               | `DateTime`                                         |
| Sync return        | `void`                 | `Void`               | `Unit`                                             |

## Create a Watch Session

Create a watch session when the current user starts viewing a room as a viewer. The SDK accepts watch sessions only for rooms in watchable states: `live` or `recorded`.

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function createRoomWatchSession(
    room: Amity.Room,
  ): Promise<string | undefined> {
    if (room.status !== "live" && room.status !== "recorded") {
      return undefined;
    }

    const sessionId = await room.analytics().createWatchSession(new Date());
    showSuccessMessage(sessionId);

    return sessionId;
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.model.video.room.AmityRoom
  import com.amity.socialcloud.sdk.model.video.room.AmityRoomStatus
  import org.joda.time.DateTime

  fun createRoomWatchSession(room: AmityRoom) {
      if (room.getStatus() != AmityRoomStatus.LIVE &&
          room.getStatus() != AmityRoomStatus.RECORDED
      ) {
          return
      }

      room.analytics()
          .createWatchSession(DateTime.now())
          .subscribe(
              { sessionId -> showSuccessMessage(sessionId) },
              { error -> handleGeneralError(error) }
          )
  }
  ```

  ```swift iOS theme={null}
  func createRoomWatchSession(for room: AmityRoom) async throws -> String? {
      guard room.status == .live || room.status == .recorded else {
          return nil
      }

      let sessionId = try await room.analytics()
          .createWatchSession(startedAt: Date())

      showSuccessMessage(sessionId)

      return sessionId
  }
  ```
</CodeGroup>

## Update Watch Duration

Update the session with the accumulated watch duration in seconds. Count only time your player considers watchable, such as active playback, and exclude buffering, paused, or backgrounded states according to your product rules.

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function updateRoomWatchSession(
    room: Amity.Room,
    sessionId: string,
    watchedSeconds: number,
  ): Promise<void> {
    await room.analytics().updateWatchSession(
      sessionId,
      watchedSeconds,
      new Date(),
    );

    showSuccessMessage(sessionId);
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.model.video.room.AmityRoom
  import org.joda.time.DateTime

  fun updateRoomWatchSession(
      room: AmityRoom,
      sessionId: String,
      watchedSeconds: Long
  ) {
      room.analytics()
          .updateWatchSession(
              sessionId = sessionId,
              duration = watchedSeconds,
              endedAt = DateTime.now()
          )
          .subscribe(
              { showSuccessMessage(sessionId) },
              { error -> handleGeneralError(error) }
          )
  }
  ```

  ```swift iOS theme={null}
  func updateRoomWatchSession(
      for room: AmityRoom,
      sessionId: String,
      watchedSeconds: Int
  ) async throws {
      try await room.analytics().updateWatchSession(
          sessionId: sessionId,
          duration: watchedSeconds,
          endedAt: Date()
      )

      showSuccessMessage(sessionId)
  }
  ```
</CodeGroup>

## Sync Pending Sessions

Call sync when the viewer leaves the playback experience or changes out of a viewer role. The SDK sync method handles pending locally stored sessions; your app decides the lifecycle event that should trigger it.

<CodeGroup>
  ```typescript TypeScript theme={null}
  function syncRoomWatchSessions(room: Amity.Room): void {
    room.analytics().syncPendingWatchSessions();
    showSuccessMessage("sync-scheduled");
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.model.video.room.AmityRoom

  fun syncRoomWatchSessions(room: AmityRoom) {
      room.analytics().syncPendingWatchSessions()
      showSuccessMessage("sync-scheduled")
  }
  ```

  ```swift iOS theme={null}
  func syncRoomWatchSessions(for room: AmityRoom) {
      room.analytics().syncPendingWatchSessions()
      showSuccessMessage("sync-scheduled")
  }
  ```
</CodeGroup>

## Tracking Boundaries

| Area              | SDK responsibility                              | App responsibility                                                              |
| ----------------- | ----------------------------------------------- | ------------------------------------------------------------------------------- |
| Session lifecycle | Create, update, and sync room watch sessions    | Decide when the viewer starts and stops watching                                |
| Watchable state   | Reject sessions for non-watchable room statuses | Check room status before creating a session                                     |
| Duration          | Store the latest duration value for the session | Calculate accumulated watch seconds from player state                           |
| Sync              | Send pending sessions with SDK sync behavior    | Trigger sync on page exit, role transition, or product-defined lifecycle events |
| Role changes      | No automatic viewer/co-host policy              | Stop viewer tracking before the user becomes host or co-host                    |

<Warning>
  Do not create watch sessions for `idle`, `ended`, `terminated`, or `error` rooms. Create sessions only after the room is `live` or `recorded`.
</Warning>

## Error Handling

| Situation                       | SDK behavior                                        | App response                                                                                |
| ------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Non-watchable room status       | Create session fails or returns an error            | Check status before calling and show a non-playable state                                   |
| Missing session ID on update    | Update fails because the session cannot be found    | Recreate tracking only if the viewer is still watching and your product wants a new session |
| Network unavailable during sync | Pending sessions stay local until sync can complete | Retry from the next appropriate lifecycle event                                             |

## Related Topics

<CardGroup cols={3}>
  <Card title="Live Room Viewing" icon="signal-stream" href="../broadcasting/live-viewing">
    Observe live room state before creating viewer sessions.
  </Card>

  <Card title="Recorded Playback" icon="play" href="../broadcasting/recorded-playback">
    Track recorded room playback after recording metadata is available.
  </Card>

  <Card title="Co-Host Management" icon="users" href="../broadcasting/co-host-management">
    Stop viewer tracking when a viewer becomes a co-host.
  </Card>
</CardGroup>
