Skip to content

Integrate analytics#

The SDK reports what users do in Stories, Clips, Polls, Quizzes, and ads through the onUserActivityOccurred callback. This page shows how to receive these events and forward them to your analytics tool, what the startup event contains, and how to add placement context. The event pages list every event and its fields.

Receive events#

Add an onUserActivityOccurred callback to Storyteller.sharedInstance.delegate before you call initialize, so you also receive the startup event. The callback receives the event type and an object with the event's fields.

Storyteller.sharedInstance.delegate = {
  onUserActivityOccurred: (type, data) => {
    analytics.track(type, data);
  },
};

await Storyteller.sharedInstance.initialize('demo-api-key');

Replace analytics.track with the call your analytics tool uses. To handle one event type, compare type with a Storyteller.ActivityType value, for example Storyteller.ActivityType.openedStory. In TypeScript, the delegate type is IStorytellerDelegate.

Assigning Storyteller.sharedInstance.delegate replaces all four global callbacks: onUserActivityOccurred, onShareButtonTapped, getAdConfig, and userNavigatedToApp. Define all your callbacks in one object, or spread the current delegate:

Storyteller.sharedInstance.delegate = {
  ...Storyteller.sharedInstance.delegate,
  onUserActivityOccurred: (type, data) => {
    analytics.track(type, data);
  },
};

The SDK calls onUserActivityOccurred only when enableUserActivityTracking is true, which is the default. Ad events also need enableAdTracking. When enableFullVideoAnalytics is false, content IDs and titles are null. See Control privacy and tracking for these options.

The Storyteller Web Showcase handles these events in onUserActivityOccurred. Handle global callbacks describes the other callbacks on the delegate.

Event types#

The SDK sends these kinds of events:

Each event page lists:

  • the events of that kind
  • when each event is recorded
  • the fields sent with each event

SDK initialization#

The SDK sends sdkInitialized (Storyteller.ActivityType.sdkInitialized) when an initialize call gets the result of the settings request for your tenant:

  • initializationSucceeded is true when the settings load. Later initialize calls after a successful one don't send the event again.
  • initializationSucceeded is false when the settings request fails. The initialize promise then rejects.

initialize rejects without sending sdkInitialized when the API key is missing, when the SDK can't save the user ID, or when the request for the user's viewing history fails. With the default privacy options, the SDK waits for the viewing history before the settings, so an invalid API key or a network outage usually fails that request first. Handle startup failures in the catch block of initialize, not with this event.

Set the delegate before you call initialize to receive this event.

Storyteller.sharedInstance.delegate = {
  onUserActivityOccurred: (type, data) => {
    if (type === Storyteller.ActivityType.sdkInitialized) {
      console.log(data.initializationSucceeded);
    }
  },
};

The event contains the following properties:

Property Value
initializationSucceeded true or false.
enableAdTracking, enableFullVideoAnalytics, enablePersonalization, enableRemoteViewingStore, enableStorytellerTracking, enableUserActivityTracking The tracking options in effect. enablePersonalization and enableStorytellerTracking are false when enableFunctionalCookies is false. The event doesn't include enableFunctionalCookies or disabledFunctionalFeatures.
appId The page origin and path, for example https://www.example.com/news, without the query string or hash. null during server rendering.
deviceType Phone, Tablet, TV, or Desktop.
deviceBrand, deviceModel Detected from the browser's user agent. 'none' when unknown.
operatingSystem, osVersion Detected from the browser's user agent. 'none' when unknown.
screenResolution The browser viewport size as <width>x<height> in CSS pixels. null during server rendering.

The callback runs when enableUserActivityTracking is enabled. Storyteller server delivery also follows enableFunctionalCookies and enableStorytellerTracking. See Control privacy and tracking for these settings.

Add placement context to events#

Use context to record where on your site an event came from, such as the page and module. context?: unknown contains host-defined attribution data. The SDK does not prescribe its shape. It returns the configured value in UserActivityData.context for events that it can attribute to the view and to content opened from that view.

You can provide context through the configuration for:

  • StorytellerStoriesRowView
  • StorytellerStoriesGridView
  • StorytellerClipsRowView
  • StorytellerClipsGridView
  • StorytellerClipsPlayerView
  • StorytellerEmbeddedClipsPlayerView
const storiesRow = new Storyteller.StorytellerStoriesRowView('stories-row');
const analyticsContext = {
  location: 'home',
  module: 'top-stories',
  sortOrder: 10,
};

storiesRow.configuration = {
  context: analyticsContext,
};

Storyteller.sharedInstance.delegate = {
  onUserActivityOccurred: (type, data) => {
    console.log(type, data.context);
  },
};

You can replace the value while the view is mounted. Reassign the configuration object with the new value:

storiesRow.configuration = {
  context: {
    location: 'sports',
    module: 'latest-stories',
  },
};

The callback is delivered only when enableUserActivityTracking is enabled. It omits context when the configured value is undefined. Explicit values such as null, false, 0, and an empty string remain in the callback.

If a Story or Clip opens related content from an SDK action, the related player events keep the source placement context. This applies to child Stories, Story categories, Clips, and Clip collections. A direct hash URL or deep link has no source placement, so the SDK uses the destination view's configured context or omits the field.

The SDK returns context only to the delegate in the same browser client. It does not add context to Storyteller analytics API requests. Your application owns the value, its storage, and its transfer to any analytics provider. Keep credentials and personal data out of this field.

Event data#

OpenedReason#

The action which the user took to open the Story:

Value Description
storyListTap The user tapped the Story in the list
deepLink The user navigated directly to a Story URL
swipe The user swiped left or right to change the Story
automaticPlayback The previous Page finished, and the player moved on to the next one
tap The user tapped to navigate

or Clip:

Value Description
clipListTap The user tapped the Clip in the list
categoryListTap The user tapped a Clip Category label
categoryBackTap The user tapped the back button in a Clip Category
deepLink The user navigated directly to a Clip URL
swipe The user swiped to the next or previous Clip

DismissedReason#

The reason the Story or Clip was dismissed:

Value Description
backgroundTapped The user tapped the background to dismiss the Story (on desktop)
closeButtonTapped The user tapped close to dismiss the Story
swipedDown The user swiped down to dismiss the Story
swipedFinalStory The user swiped the final Story to dismiss it
swipedFirstStory The user swiped the first Story to dismiss it
skippedFinalPage The user tapped to skip the final Page of the final Story
backTapped The user tapped the browser back button to dismiss the Story view
backButtonTapped The user tapped the back button to dismiss the Clips player
completedFinalPage The user completed the final Page of the final Story
instanceMethod The player was dismissed programmatically using the dismissPlayer method
escapeKeyPressed The user pressed the Esc key to dismiss the Story
windowUnload The user navigated away by closing the page or entering a new URL in the browser bar