These are the various events which are triggered from within the SDK. Each event is a member of the StorytellerUserActivity.EventType enumeration. Follow Integrate Analytics to retain the delegate, choose tracking options, forward events, and verify the integration.
For a concrete analytics integration, see the Showcase forwarding implementation in StorytellerTrackingDelegate.
In the below discussion, "completing" a Page refers to allowing the timer to expire - so this would correspond to watching all of an Image Page for the duration set for it (default 15s) or watching all of a video.
This event is recorded in the following scenarios:
When a user taps on a row item to open a story
When a story is loaded because the previous Story finished
When a story is loaded because the user tapped to skip the last page of the previous story
When a user swipes left on a story to go to the next story
When a user swipes right on a story to go to the previous story
When a user is sent directly to a story via a deep link
Whenever an Opened Story event occurs, additional event data specific to this event includes storyReadStatus, categories, categoryDetails, storyIndex, and openedReason.
This event is recorded whenever a user views content from a page.
Opened Page is one of the most important events to track as it is equal to a video start, one of the most important measures of engagement. By tracking this event, you can monitor valuable information about user engagement with your app.
Whenever an Opened Page event occurs, additional event data specific to this event includes openedReason.
This event is recorded when a user swipes left to go to the next story (not on the last page).
Note: This event is not fired when the user swipes on the last page of a story. In that case, the user has consumed all pages and is naturally moving to the next story or dismissing the player, which is not considered a "skip".
This event is recorded when a user answers a question in a trivia quiz.
Whenever a Trivia Quiz Question Answered event occurs, additional event data specific to this event includes triviaQuizId, triviaQuizTitle, triviaQuizQuestionId, and triviaQuizAnswerId.
This event is recorded when a user completes a trivia quiz.
Whenever a Trivia Quiz Completed event occurs, additional event data specific to this event includes triviaQuizId, triviaQuizTitle, and triviaQuizScore.
a user taps on the back button in the top-left to exit the Clips player (and is at the top of the stack of Clip Categories)
This event does not fire when the user is not at the top of the Clip Category stack.
Whenever a Dismissed Clip event occurs, additional event data specific to this event includes dismissedReason, durationViewed, clipsViewed, and loopsViewed.
a user taps the primary action button at the bottom of a Clip
a user taps any secondary action buttons above the clip title
a user swipes left on a clip to open the relevant action
Whenever an Action Button Tapped event occurs, additional event data specific to this event includes actionText, actionClass, actionIndex, tappedClipActionText, tappedClipActionUrl, and tappedClipActionType.
a user taps on the screen whilst a clip is playing to pause the clip - it does not fire when a clip is paused automatically by sharing or following an action
Note: For live clips this event will never be fired, as pausing/resuming live clips is not supported.
a user scrubs the clip to a different position by dragging the clip progress bar
Whenever a Scrubbed Clip event occurs, additional event data specific to this event includes openedReason, startPosition, endPosition, and scrubDirection.
the alert dialogue box associated with the Followable Category Limit is shown
Whenever a Followable Category Limit Shown event occurs, additional event data specific to this event includes followableCategoryLimitDialogue, followableCategoryLimitActionText, and followableCategoryLimitActionUrl.
a user taps on the customisable action button in the Followable Category Limit Dialogue Box
Whenever a Followable Category Limit Action Button Tapped event occurs, additional event data specific to this event includes followableCategoryLimitDialogue, followableCategoryLimitActionText, and followableCategoryLimitActionUrl.
a user dismisses the Followable Category Limit Dialogue Box by tapping the cancel action button
Whenever a Followable Category Limit Dismissed event occurs, additional event data specific to this event includes followableCategoryLimitDialogue, followableCategoryLimitActionText, and followableCategoryLimitActionUrl.
This event is recorded when a Story or Clip tile becomes visible in a Storyteller list row or grid.
It is recorded in the following scenarios:
when list data is rendered and one or more tiles are visible
when a user scrolls and new tiles become visible
when a list reloads or refreshes with updated content and visible tiles are re-evaluated
This event is not recorded again while the same tile remains continuously visible, and it is not recorded just because the app returns from the background or the Story/Clip Player is dismissed if the same visible tiles remain and the list did not reload or scroll.
Whenever a Tile Visible event occurs, additional event data specific to this event includes tileIndex. Story tile events include storyId, storyTitle, categories, and context when available. Clip tile events include clipId, clipTitle, collection, categories, and context when available.
a visible video Storyteller Card naturally loops and starts the next playback cycle
This event is only emitted for video cards.
Whenever a Card Video Started event occurs, additional event data specific to this event includes videoStartReason.
For Card Video Started, videoStartReason is natural for the first visible playback start of the current Card session and loop when the same visible Card naturally restarts after a completed loop.
a visible video Storyteller Card reaches 5 seconds, 10 seconds, 15 seconds, and so on of active playback within the current loop
This event is only emitted for video cards.
Whenever a Card Video Heartbeat event occurs, additional event data specific to this event includes durationViewed.
For Card Video Heartbeat, durationViewed is reported in milliseconds, counts active playback only, accumulates through pauses, buffering, backgrounding, and other interruptions within the same loop, and resets when the video starts a new loop.
a user toggles audio for an active video Storyteller Card
This event is only emitted for video Cards where audio can be controlled. It is not emitted for no-audio Cards, behavior-locked muted Cards, inactive Cards, or interruption-forced mutes.
Whenever a Card Audio Toggled event occurs, additional event data specific to this event includes audioToggleFrom, audioToggleTo, and isMuted. isMuted reflects the resulting state after the toggle.
Ad-related events include both ad interaction events (for example OpenedAd, DismissedAd) and paid ad operational events (for example AdOpportunity, AdRequested). Not every field is present on every ad event type.
The following properties may be included in ad-related events:
adFormat
adId
adIndex
adPlacement
adResponseIdentifier
adStrategy
adType
adUnitId
advertiserName
airplayEnabled
categories
categoryDetails
clipActionText
clipActionType
clipHasAction
contentLength
currentCategory
isMuted
pageActionText
pageActionType
pageActionUrl
pageHasAction
searchTerm
context
For Ad Opportunity events, additional fields include:
playerSessionId
adSlotType
For Ad Requested events, additional fields include:
playerSessionId
adRequestId
adSlotType
adUnitId
adSource
For Ad Loaded events, additional fields include:
playerSessionId
adRequestId
adSlotType
adUnitId
adSource
adSourceName
adSourceId
adSourceInstanceName
adSourceInstanceId
adAdapterLatencyMillis
adMediationGroupName
adMediationAbTestName
adMediationAbTestVariant
For Ad Failed To Load events, additional fields include:
playerSessionId
adRequestId
adSlotType
adUnitId
adSource
adErrorCode
adErrorDomain
adErrorMessage
adAdapterLatencyMillis
For Ad Paid events, additional fields include:
playerSessionId
adRequestId
adSlotType
adUnitId
adSource
adSourceName
adSourceId
adSourceInstanceName
adSourceInstanceId
adAdapterLatencyMillis
adValueMicros
adCurrencyCode
adValuePrecision
For Story Ad events specifically, additional common fields include:
storyId
pageId
pageActionText
pageActionType
pageActionUrl
pageHasAction
pageType
storyPlaybackMode
For Clip Ad events specifically, additional common fields include:
This event is recorded when the SDK reaches an eligible ad slot and is about to request an ad.
This can happen for:
full-screen ads in Stories
full-screen ads between clips
bottom banner ads in the Clips player
Whenever an Ad Opportunity event occurs, additional event data specific to this event includes playerSessionId and adSlotType.
AdOpportunity also includes the same contextual ad fields as OpenedAd when they are available at opportunity time (for example storyId, pageId, storyPlaybackMode, categories, currentCategory, pageActionType, pageHasAction, pageActionText, pageActionUrl, clipId, clipActionType, clipHasAction, clipActionText, clipActionUrl).
Some differences between AdOpportunity and OpenedAd are expected by design because they are captured at different moments: AdOpportunity is a slot-time snapshot (before the ad request), while OpenedAd is captured when the rendered ad is opened.
This event is recorded when the SDK initiates an Ad request. This event is emitted only for Google Ad sources (GAM and AdMob).
This can happen for:
full-screen ads in Stories
full-screen ads between clips
bottom banner ads in the Clips player
Whenever an Ad Requested event occurs, additional event data specific to this event includes playerSessionId, adRequestId, adSlotType, adUnitId, and adSource.
For GAM and AdMob integrations supplied by Storyteller, adUnitId is the exact unit used for that request attempt. If AdMob falls back between native and banner formats, each concrete attempt emits its own AdRequested event with the corresponding unit and the same adRequestId.
If a Google module fails before it can resolve a unit or start a concrete provider load, the SDK preserves the request/failure event pair with adUnitId set to nil.
This event is recorded when the SDK successfully loads an ad and considers it available for rendering (even if it is not ultimately shown). This event is emitted only for Google Ad sources (GAM and AdMob).
This can happen for:
full-screen ads in Stories
full-screen ads between clips
bottom banner ads in the Clips player
Whenever an Ad Loaded event occurs, additional event data specific to this event includes playerSessionId, adRequestId, adSlotType, adUnitId, adSource, adSourceName, adSourceId, adSourceInstanceName, adSourceInstanceId, adAdapterLatencyMillis, adMediationGroupName, adMediationAbTestName, and adMediationAbTestVariant.
adUnitId identifies the successful unit. Response metadata takes precedence when it differs from the requested unit.
This event is recorded when the SDK fails to load an Ad request (including no-fill). This event is emitted only for Google Ad sources (GAM and AdMob).
This can happen for:
full-screen ads in Stories
full-screen ads between clips
bottom banner ads in the Clips player
Whenever an Ad Failed To Load event occurs, additional event data specific to this event includes playerSessionId, adRequestId, adSlotType, adUnitId, adSource, adErrorCode, adErrorDomain, adErrorMessage, and adAdapterLatencyMillis.
adUnitId identifies the concrete unit used by the failed request attempt. It is nil when the module failed before resolving a unit or starting the provider load.
This event is recorded when the SDK receives impression-level paid revenue info for an Ad from Google Ad sources.
This can happen for:
full-screen ads in Stories
full-screen ads between clips
bottom banner ads in the Clips player
Whenever an Ad Paid event occurs, additional event data specific to this event includes playerSessionId, adRequestId, adSlotType, adUnitId, adSource, adSourceName, adSourceId, adSourceInstanceName, adSourceInstanceId, adAdapterLatencyMillis, adValueMicros, adCurrencyCode, and adValuePrecision.
This event is recorded once when a root Storyteller player session ends (Clips or Stories). If a prior session was persisted without being ended cleanly, this summary can also be emitted on the next SDK initialize. The session spans app background/foreground transitions and is not restarted until the root player session ends.
The summary aggregates paid ads activity for that player session:
playerSessionId
adSessionOpportunitiesCount
adSessionRequestsCount
adSessionLoadsCount
adSessionFailedToLoadCount
adSessionPaidCount
adSessionRevenueMicros (optional)
adSessionCurrencyCode (optional)
adSessionRevenueMicros and adSessionCurrencyCode are only included when all paid events in that session can be represented as a single currency with complete paid data.
Whenever an Ad Session Summary event occurs, additional event data specific to this event includes playerSessionId, adSessionOpportunitiesCount, adSessionRequestsCount, adSessionLoadsCount, adSessionFailedToLoadCount, adSessionPaidCount, adSessionRevenueMicros (optional), and adSessionCurrencyCode (optional).
adUnitId is nil for AdSessionSummary because a session can aggregate requests across multiple ad units.
This event is recorded at the same time as Dismissed Ad, Skipped Ad and Viewed Ad Page Complete and gives an easier way to determine when an ad finishes for any reason.
Whenever a Finished Ad event occurs, additional event data specific to this event includes adView.
This event is recorded when a user pauses a clip which is an ad by tapping the screen. It does not fire when a clip is paused automatically for sharing or following an action.
This event is fired when a clip which is an ad is paused and a user taps the screen to resume playback. It does not fire when a clip is resumed automatically.
This event is called on video pages whenever the video finishes buffering.
Note: There should be at most one Ready to Play event and one Media Started event for every page. There may be multiple Buffering Started/Buffering Ended pairs of events for an individual page. There may not always be a Buffering Ended event for every Buffering Started event as the user may choose to exit the page during buffering.
Whenever a Buffering Ended event occurs, additional event data specific to this event includes isInitialBuffering and timeSinceBufferingBegan.
A user taps the 'Search' icon after entering a term in the Search bar (whether manually or by tapping the 'arrow' icon beside a Search suggestion to populate the search bar)
A user taps the 'Search' icon beside a Search suggestion. The Search is then performed with the suggestion as the term.
A user taps 'Apply filters' from the filters interface.
A user taps the 'arrow' icon beside a Search suggestion to populate the Search bar. This does not trigger any other event, and the user may amend the Search bar input before performing a Search.
A user taps the 'Search' icon beside a Search suggestion. This simultaneously triggers a PerformedSearch event, above.
Whenever a Used Suggestion event occurs, additional event data specific to this event includes initialInput.
For each event, data is returned with details about the story and page involved as well as some extra properties with more information about what the user has done. The data is returned as a StorytellerUserActivityData class with the following properties:
The storyIndex: Int? is the index of the story for which the event occurred in the row from which it was opened at the point it was opened - this is only included on OpenedStory events.
The storyPlaybackMode: String? value states if the story was opened during the list or in the single story mode (Storyteller static method.) This is included for all events. The values for this are either list or singleStory.
The actionLinkId: String? is the unique identifier of the action associated with the current story page, clip or card. This is not included for Ad events.
The openedReason: String? value states how the user opened a Story or Clip. The possible values for this are:
- storyListTap: The user tapped the Story in the Story row.
- clipListTap: The user tapped the Clip in a Clip list.
- deepLink: openStory or openPage was called to open the Story.
- swipe: The user swiped left or right to change the current Story.
- automaticPlayback: The user completed the previous Page.
- card: The user taps on a Card.
- clipActionButton: The user clicked on an action button in the Clips player.
- pageActionButton: The user clicked on the action button in the Story player.
- tap: The user tapped on the next or previous Story Page to navigate to this page.
- instanceMethod: Storyteller.shared.openStory(id:) or Storyteller.shared.openPage(id:) was called to open a Story or a Page.
- loop: The user completes a loop of a Clip naturally or by scrubbing to the end of the Clip's duration.
openedReason is only included on OpenedStory, OpenedClip, OpenedPage, StoryInstructionsScreenViewed, CompletedLoop, OpenedAd and OpenedSheet events.
The videoStartReason: String? value states why a Card video start was emitted. The possible values are natural (the first visible playback start for the Card session) and loop (the Card video completed a loop and restarted while still visible).
videoStartReason is only included on CardVideoStarted events.
The dismissedReason: String? value states the way the user dismissed a story or clip. The possible values for this are closeButtonTapped (the user tapped close to dismiss the story); swipedDown (the user swiped down to dismiss the story); swipedFirstStory (the user swiped the first story to dismiss it); swipedFinalStory (the user swiped the final story to dismiss it); skippedFinalPage (the user tapped to skip the final page of the final story); completedFinalPage (the user completed the final page of the final story) and backButtonTapped (the user tapped the back button to dismiss the clip).
dismissedReason is only included on DismissedStory and DismissedClip events.
The durationViewed: Float? is the duration the user viewed the story or clip for in milliseconds. This is measured from the most recent OpenedStory or OpenedClip event with an Opened Reason of storyRowTap, deepLink, card, pageActionButton, clipActionButton or clipsListTap.
This timer is reset after any DismissedStory or DismissedClip events.
For FinishedClip, Duration Viewed is the duration the user viewed the clips player for in milliseconds. This is measured from the most recent OpenedClip event with an Opened Reason of swipe.
For CardVideoHeartbeat and CardVideoCompleted, durationViewed is the active playback duration for the current card-video loop in milliseconds. It accumulates through pauses, buffering, backgrounding, and other interruptions within the same loop, and resets when a new loop starts.
The audioToggleFrom: String? and audioToggleTo: String? values state the previous and resulting Cards audio state for CardAudioToggled events. Possible values are muted and unmuted.
The pagesViewedCount: Int? is the total number of pages a user has viewed since the most recent OpenedStory event with an Opened Reason of storyRowTap, pageActionButton, clipActionButton, card or deepLink. This count is reset after any DismissedStory events.
The adPlacement: String? represents the placement of the ad. It can be either Between Stories, Between Pages or Between Clips. This is only included for ad events.
For Story ad events, AdOpportunity and OpenedAd use the same placement naming (Between Stories / Between Pages).
The adStrategy: String? represents the strategy used to display the ads. It can have the following values: Between Stories, Between Pages, Between Stories and Pages, Between Clips.
The adResponseIdentifier: String? represents the response identifier attached to the ad that was received from the ad provider. Used for debugging ad targeting.
The adIndex: Int? represents the order of the Ad within the displayed Ads in a Story or Clip collection (1 for the first Ad, 2 for the second, etc.). This field is included in all ad-related events.
The playerSessionId: String? is a unique identifier for the current root player session. This is included on AdOpportunity, AdRequested, AdLoaded, AdFailedToLoad, AdPaid, and AdSessionSummary events.
The adRequestId: String? is a unique identifier that correlates an ad request chain. This is included on AdRequested, AdLoaded, AdFailedToLoad, and AdPaid events. Concrete native/banner fallback attempts share the same identifier.
The adSlotType: String? indicates the type of ad slot for AdOpportunity, AdRequested, AdLoaded, AdFailedToLoad, and AdPaid events. Possible values are fullScreen and bottomBanner.
The adUnitId: String? is the exact ad unit identifier when it is known. It is available on paid ad operational events and is retained on rendered ad interaction events such as OpenedAd, DismissedAd, quartile events, and FinishedAd.
For Storyteller GAM and AdMob integrations, the SDK records the unit immediately before each concrete request attempt. For GAM VAST ads, it uses the final iu tag parameter after client overrides. Host-supplied custom modules can provide the value through StorytellerAd.adUnitId.
adUnitId is nil for AdOpportunity because provider and unit selection have not occurred yet, and for AdSessionSummary because the event aggregates multiple requests. It can also be nil for Storyteller First Party Ads, direct VAST ads, or custom modules that do not supply a unit.
The adSource: String? is the high-level source for ad events. Supported values include storyteller for Storyteller First Party Ads, gam, admob, and custom source values provided by integrating-app modules via StorytellerModule.adSource. This is included on all ad-related events. For AdOpportunity, adSource is always nil because the event is emitted before ad module resolution. For other ad events, adSource may still be nil when the source cannot be resolved.
The adMediationGroupName: String? is the mediation group name returned by the ad provider when available. This is included on AdLoaded events when available.
The adMediationAbTestName: String? is the mediation A/B test name returned by the ad provider when available. This is included on AdLoaded events when available.
The adMediationAbTestVariant: String? is the mediation A/B test variant returned by the ad provider when available. This is included on AdLoaded events when available.
The adAdapterLatencyMillis: Int? is the elapsed time in milliseconds for the concrete ad request attempt that produced the result. When native/banner fallback occurs, load, failure, and paid events use the final attempt's latency. This is included on AdLoaded, AdFailedToLoad, and AdPaid events.
The adValuePrecision: String? indicates how precise the paid value is. Possible values are UNKNOWN, ESTIMATED, PUBLISHER_PROVIDED, and PRECISE. This is only included on AdPaid events.
The adSessionOpportunitiesCount: Int? is the total number of ad opportunities tracked in the player session. This is only included on AdSessionSummary events.
The adSessionRequestsCount: Int? is the total number of ad-module request attempts initiated in the player session. Native/banner fallback attempts are counted separately, and a module failure before provider load counts once, so this value can exceed the number of ad opportunities. This is only included on AdSessionSummary events.
The adSessionRevenueMicros: Int? is the aggregated session paid value in micros. This is only included on AdSessionSummary events when all paid callbacks in the session use one currency and include complete paid data.
The adSessionCurrencyCode: String? is the ISO 4217 currency code associated with adSessionRevenueMicros. This is only included on AdSessionSummary events when all paid callbacks in the session use one currency and include complete paid data.
The isInitialBuffering: Boolean? value is returned if the buffering happens at the start of playback for that page. This is only included for BufferingStarted and BufferingEnded events.
The timeSinceBufferingBegan: TimeInterval? value is the duration the current buffering lasted for in milliseconds. This is only included for BufferingEnded events.
The categories: [String]? value is the list of categories assigned to the story or clip for which the event occurred. This is included on OpenedStory and TileVisible events, and may be included on other story, clip, ad, card, search, or sheet events when category context is available.
The triviaQuizId: String? is the ID of the trivia quiz that was completed or answered. This is only included on TriviaQuizQuestionAnswered and TriviaQuizCompleted events.
The triviaQuizTitle: String? is the title of the trivia quiz that was completed or answered. This is only included on TriviaQuizQuestionAnswered and TriviaQuizCompleted events.
The triviaQuizQuestionId: String? is the ID of the trivia quiz question which was answered. This is only included on TriviaQuizQuestionAnswered events.
The clipIndex: Int? is the index of the clip in the row or grid at the point it was selected or the index of the clip in the player inside the original row or grid. For Ad events, clip index refers to the index of the clip before the Ad.
The tileIndex: Int? is the index of the Story or Clip tile in the row or grid at the point it became visible. This is only included on TileVisible events.
The clipsViewed: Int? value is the total number of clips a user has viewed since the most recent OpenedClip event with an Opened Reason of clipListTap, pageActionButton, card, clipActionButton or deepLink. This count should be reset after any DismissedClip events.
The loopsViewed: Int? is for DismissedClip, the total number of loops (plays of an individual clip) a user has viewed since the most recent OpenedClip event with an Opened Reason of clipListTap, pageActionButton, card, clipActionButton or deepLink.
This count should be reset after any DismissedClip events. For FinishedClip, the total number of loops.
The currentCategory is the category for the row that is currently being interacted with. The information provided from this is the category title, ID and placement.
The captionsEnabled property indicates whether captions are currently enabled for the Clips Player. This is included in all Clip Analytics Events and represents the state of captions at the time the event occurred.
The startPosition: Int? represents the playback position, in milliseconds, when the user started scrubbing the clip. This is only included for ScrubbedClip events.
The endPosition: Int? represents the playback position, in milliseconds, when the user stopped scrubbing the clip. This is only included for ScrubbedClip events.
The scrubDirection: String? indicates whether the user scrubbed to a position forward or backward on a Clip. Possible values are forward and backward. This is only included for ScrubbedClip events.
The completionType: String? indicates how a user finished watching a Clip. Possible values are natural and scrubbed.
This is included for FinishedClip and ClipCompletedLoop events.
The actionText: String? property is used for general action text and can apply to both page actions and clip actions depending on the placement context.
The actionType: String? property is used for general action types, and can apply to both page actions and clip actions depending on the placement context.
The actionUrl: String? is the URL for the action link. This property is used for general action URLs in events and can apply to both page actions and clip actions depending on the placement context.
The actionClass: String? identifies whether the action button that was tapped is a primary or secondary action. Possible values are primary and secondary. This is only included for ClipActionButtonTapped events.
The actionIndex: Int? is the 1-based index of the secondary action that was tapped. This is only included for ClipActionButtonTapped events when a secondary action is tapped.
The tappedClipActionText: String? is the text of the specific action button (primary or secondary) that was tapped. This is only included for ClipActionButtonTapped events.
The tappedClipActionUrl: String? is the URL of the specific action button (primary or secondary) that was tapped. This is only included for ClipActionButtonTapped events.
The tappedClipActionType: String? is the type of the specific action button (primary or secondary) that was tapped. This is only included for ClipActionButtonTapped events.
The clipSecondaryActionsText: [String]? is an array of all the text CTAs on secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.
The clipSecondaryActionUrls: [String]? is an array of all the URLs on secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.
The clipSecondaryActionTypes: [String]? is an array of all the types of secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.
The SDK does not emit a hasAction property. Use pageHasAction (story/page-based ad events) or clipHasAction (clip-based ad events) depending on the ad placement context.
The followableCategoryLimitDialogue: String? is the text displayed in the Followable Category Limit dialogue box. This is included for FollowableCategoryLimitShown, FollowableCategoryLimitActionButtonTapped, and FollowableCategoryLimitDismissed events.
The followableCategoryLimitActionText: String? is the text displayed on the customisable action button in the Followable Category Limit dialogue box. This is included for FollowableCategoryLimitShown, FollowableCategoryLimitActionButtonTapped, and FollowableCategoryLimitDismissed events.
The followableCategoryLimitActionUrl: String? is the URL associated with the customisable action button in the Followable Category Limit dialogue box. This is included for FollowableCategoryLimitShown, FollowableCategoryLimitActionButtonTapped, and FollowableCategoryLimitDismissed events.
The isMuted: Bool? indicates whether the audio is currently muted when the event occurred. This property is included in all Story, Clip, Ad, and video Card analytics events when the mute state is known and represents the mute state at the time the event was tracked. Permanently muted video Cards and video Cards marked as having no audio report true; image and non-video Card events report nil.
The metadata: [String: String]? contains custom metadata associated with the content for which the event occurred. For Clip events, this contains the metadata from the associated clip. For Story events, this contains the metadata from the associated page. This property is included in all Story and Clip analytics events.
context: StorytellerAnalyticsContext? contains host-defined attribution data. StorytellerAnalyticsContext is a type alias for [String: String]; the SDK does not prescribe the keys.
You can provide context through:
StorytellerStoriesListConfiguration
StorytellerClipsListConfiguration
StorytellerClipCollectionConfiguration
StorytellerCardConfiguration
StorytellerHomeConfiguration
The SDK carries that context into StorytellerUserActivityData.context for events it can attribute to the configured surface and content opened from it. Consume it in StorytellerDelegate.onUserActivityOccurred:
importStorytellerSDKletanalyticsContext:StorytellerAnalyticsContext=["location":"home","campaign":"summer-league"]letclipsConfiguration=StorytellerClipsListConfiguration(collectionId:"top-plays",context:analyticsContext)finalclassAnalyticsDelegate:StorytellerDelegate{funconUserActivityOccurred(type:StorytellerUserActivity.EventType,data:StorytellerUserActivityData){guardletlocation=data.context?["location"]else{return}print("Storyteller event \(type) came from \(location)")}}
The callback is delivered only when enableUserActivityTracking is enabled. Ad events are additionally gated by enableAdTracking.
The Showcase app demonstrates an optional app-defined key namespace and consumption in StorytellerTrackingDelegate.
{"slug": "analytics", "page_title": "Browse Analytics Events", "page_url": "Analytics/", "canonical_url": "/ios/Analytics/", "markdown": "# Analytics\n\n## Table of Contents\n\n1. [Event Types](#event-types)\n1. [Story Events](#story-events)\n1. [Clip Events](#clip-events)\n1. [List Tile Events](#list-tile-events)\n1. [Card Events](#card-events)\n1. [Ad Events](#ad-events)\n1. [Playback Events](#playback-events)\n1. [Sheet Events](#sheet-events)\n1. [Search Events](#search-events)\n1. [Event Data](#event-data)\n\n## Event Types\n\nThese are the various events which are triggered from within the SDK. Each event is a member of the `StorytellerUserActivity.EventType` enumeration. Follow [Integrate Analytics](AnalyticsIntegration.md) to retain the delegate, choose tracking options, forward events, and verify the integration.\n\nFor a concrete analytics integration, see the Showcase forwarding implementation in [`StorytellerTrackingDelegate`](https://github.com/getstoryteller/storyteller-showcase-ios/blob/11.6.1/main/ShowcaseApp/Analytics/StorytellerTrackingDelegate.swift#L10).\n\nIn the below discussion, \"completing\" a Page refers to allowing the timer to expire - so this would correspond to watching all of an Image Page for the duration set for it (default 15s) or watching all of a video.\n\n## Story Events\n\nThe following properties are included in Story-related events:\n\n- `airplayEnabled`\n- `captionsEnabled`\n- `contentLength`\n- `currentCategory`\n- `eyebrow`\n- `isMuted`\n- `metadata`\n- `pageActionText`\n- `pageActionType`\n- `pageActionUrl`\n- `actionLinkId`\n- `pageHasAction`\n- `pageId`\n- `pageIndex`\n- `pageTitle`\n- `pageType`\n- `storyDisplayTitle`\n- `storyId`\n- `storyPageCount`\n- `storyPlaybackMode`\n- `storyTitle`\n- `context`\n\n### Opened Story\n\nThis event is recorded in the following scenarios:\n\n- When a user taps on a row item to open a story\n- When a story is loaded because the previous Story finished\n- When a story is loaded because the user tapped to skip the last page of the previous story\n- When a user swipes left on a story to go to the next story\n- When a user swipes right on a story to go to the previous story\n- When a user is sent directly to a story via a deep link\n\nWhenever an Opened Story event occurs, additional event data specific to this event includes `storyReadStatus`, `categories`, `categoryDetails`, `storyIndex`, and `openedReason`.\n\n### Opened Page\n\nThis event is recorded whenever a user views content from a page.\n\nOpened Page is one of the most important events to track as it is equal to a video start, one of the most important measures of engagement. By tracking this event, you can monitor valuable information about user engagement with your app.\n\nWhenever an Opened Page event occurs, additional event data specific to this event includes `openedReason`.\n\n### Dismissed Story\n\nThis event is recorded in the following scenarios:\n\n- When a user taps the close button to dismiss the story\n- When a user swipes down to dismiss the story\n- When a user taps to skip the last page of the final story - this dismisses the story and exits the story view\n- When a user swipes left on the final story to dismiss the story\n- When a user swipes right on the first story to dismiss the story\n- When a user completes the final page of the final story and the story view is dismissed\n\nWhenever a Dismissed Story event occurs, additional event data specific to this event includes `dismissedReason`, `durationViewed`, and `pagesViewedCount`.\n\n### Skipped Story\n\nThis event is recorded when a user swipes left to go to the next story (not on the last page).\n\n> Note: This event is not fired when the user swipes on the last page of a story. In that case, the user has consumed all pages and is naturally moving to the next story or dismissing the player, which is not considered a \"skip\".\n\n### Skipped Page\n\nThis event is recorded when a user taps to go to the next page before completing the current page.\n\n### Completed Story\n\nThis event is recorded at the same time as `OpenedPage` for the final page in a story.\n\n### Completed Page\n\nThis event is recorded when a user watches a page to completion (i.e. the timer for that page finishes.)\n\n### Action Button Tapped\n\nThis event is recorded when a user taps an action button on a page to open a link.\n\nWhenever an Action Button Tapped event occurs, additional event data specific to this event includes `actionText`.\n\n### Share Button Tapped\n\nThis event is recorded when a user taps the share button on a page.\n\nWhenever a Share Button Tapped event occurs, additional event data specific to this event includes `shareMethod`.\n\n### Previous Story\n\nThis event is recorded when:\n\n- a user swipes right to go to the previous story (unless this is the first story - in which case `DismissedStory` is fired instead)\n- a user taps back on the first page in a story (and this is not the first page in the first story)\n\n### Previous Page\n\nThis event is recorded when a user taps back to go to a previous page in the story.\n\n### Share Success\n\nThis event is recorded when a user selects a sharing method from the system dialog.\n\nWhenever a Share Success event occurs, additional event data specific to this event includes `shareMethod`.\n\n### Voted Poll\n\nThis event is recorded when user votes in a poll.\n\nWhenever a Voted Poll event occurs, additional event data specific to this event includes `pollAnswerId`.\n\n### Trivia Quiz Question Answered\n\nThis event is recorded when a user answers a question in a trivia quiz.\n\nWhenever a Trivia Quiz Question Answered event occurs, additional event data specific to this event includes `triviaQuizId`, `triviaQuizTitle`, `triviaQuizQuestionId`, and `triviaQuizAnswerId`.\n\n### Trivia Quiz Completed\n\nThis event is recorded when a user completes a trivia quiz.\n\nWhenever a Trivia Quiz Completed event occurs, additional event data specific to this event includes `triviaQuizId`, `triviaQuizTitle`, and `triviaQuizScore`.\n\n### Story Instructions Screen Viewed\n\nThis event is recorded when:\n\n- The Story instruction screen appears to users\n\nWhenever a Story Instructions Screen Viewed event occurs, additional event data specific to this event includes `storyReadStatus` and `openedReason`.\n\n### Muted Story\n\nThis event is recorded when:\n\n- A user mutes a Story by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n### Unmuted Story\n\nThis event is recorded when:\n\n- A user unmutes a Story by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n## Clip Events\n\nThe following properties are included in all Clip-related events:\n\n- `airplayEnabled`\n- `captionsEnabled`\n- `categories`\n- `categoryDetails`\n- `clipActionText`\n- `clipActionType`\n- `clipActionUrl`\n- `actionLinkId`\n- `clipCollectionCount`\n- `clipFeedType`\n- `clipHasAction`\n- `clipHasSecondaryActions`\n- `clipId`\n- `clipIndex`\n- `clipSecondaryActionTypes`\n- `clipSecondaryActionUrls`\n- `clipSecondaryActionsText`\n- `clipTitle`\n- `contentLength`\n- `isLive`\n- `isMuted`\n- `metadata`\n\nThe following additional properties may be included when available:\n\n- `eyebrow`\n- `collection`\n- `collectionTitle`\n- `categoryId`\n- `categoryName`\n- `context`\n\n### Opened Clip\n\nThis event is recorded when:\n\n- a user taps on a row or grid item to open a clip\n- a user swipes up to the next clip\n- a user swipes down to the previous clip\n- a user is sent directly to a clip via a call to `openCollection`\n- a user is sent directly to a clip via a deep link\n- a user opens a Category and navigates to a new Clip or moves back to a previous Category\n- a user dismisses the last Category (by pressing back or swiping right) and returns to the top-level Collection\n- a user opens embedded Clips for the first time.\n- a user pulls to refresh at the top of Embedded Clips.\n- a user is viewing a Collection with \"For You/Following\" enabled and switches between \"For You\" and \"Following\".\n\nWhenever an Opened Clip event occurs, additional event data specific to this event includes `openedReason`.\n\n### Dismissed Clip\n\nThis event is recorded when:\n\n- a user taps on the back button in the top-left to exit the Clips player (and is at the top of the stack of Clip Categories)\n\nThis event does not fire when the user is not at the top of the Clip Category stack.\nWhenever a Dismissed Clip event occurs, additional event data specific to this event includes `dismissedReason`, `durationViewed`, `clipsViewed`, and `loopsViewed`.\n\n### Next Clip\n\nThis event is recorded when:\n\n- a user swipes up to go to the next clip\n\n### Previous Clip\n\nThis event is recorded when:\n\n- a user swipes down to go to the previous clip\n\n### Completed Loop\n\nThis event is recorded when:\n\n- a user completes a loop of a clip\n\nWhenever a Completed Loop event occurs, additional event data specific to this event includes `completionType`.\n\n> Note: For live clips this event will never be fired.\n\n### Action Button Tapped\n\nThis event is recorded when:\n\n- a user taps the primary action button at the bottom of a Clip\n- a user taps any secondary action buttons above the clip title\n- a user swipes left on a clip to open the relevant action\n\nWhenever an Action Button Tapped event occurs, additional event data specific to this event includes `actionText`, `actionClass`, `actionIndex`, `tappedClipActionText`, `tappedClipActionUrl`, and `tappedClipActionType`.\n\n### Share Button Tapped\n\nThis event is recorded when:\n\n- a user taps the share button on a clip\n\n### Share Success\n\nThis event is recorded when:\n\n- a user selects and successfully shares a page from the system dialog\n\nWhenever a Share Success event occurs, additional event data specific to this event includes `shareMethod`.\n\n### Paused Clip\n\nThis event is recorded when:\n\n- a user taps on the screen whilst a clip is playing to pause the clip - it does not fire when a clip is paused automatically by sharing or following an action\n\n> Note: For live clips this event will never be fired, as pausing/resuming live clips is not supported.\n\n### Resumed Clip\n\nThis event is recorded when:\n\n- a user taps a clip that is paused to resume playback - it does not fire when a clip is resumed automatically\n\n> Note: For live clips this event will never be fired, as pausing/resuming live clips is not supported.\n\n### Scrubbed Clip\n\nThis event is recorded when:\n\n- a user scrubs the clip to a different position by dragging the clip progress bar\n\nWhenever a Scrubbed Clip event occurs, additional event data specific to this event includes `openedReason`, `startPosition`, `endPosition`, and `scrubDirection`.\n\n### Liked Clip\n\nThis event is recorded when:\n\n- a user likes a clip by tapping the like button when they do not currently like the clip\n\n### Unliked Clip\n\nThis event is recorded when:\n\n- a user unlikes a clip by tapping the like button when they currently like the clip\n\n### Finished Clip\n\nThis event is recorded when:\n\n- Dismissed Clip is fired\n- Next Clip is fired\n- Previous Clip is fired\n- Opened Category is fired\n- The clip reaches the end and starts a new loop\n- A user is viewing a Collection with \"For You/Following\" enabled and switches between \"For You\" and \"Following\"\n\nWhenever a Finished Clip event occurs, additional event data specific to this event includes `loopsViewed`, `durationViewed`, and `completionType`.\n\n### Opened Category\n\nThis event is recorded when:\n\n- a user taps a category at the bottom of the Clips Player to open a new Category\n- a user opens a category by navigating back from another category\n\n> Note: This event is not fired when opening the top level of a collection - only when navigating to a specific category.\n\n### Dismissed Category\n\nThis event is recorded when:\n\n- a user navigates back using the back button to the previous category.\n\nThis event does not fire when dismissing the top level collection\n\n### Follow Category\n\nThis event is recorded when:\n\n- a user taps the plus button under the follow category button of the Clips Player\n- a user taps the follow button at the top right of the Followable Category screen and the category was not followed\n\n### Unfollow Category\n\nThis event is recorded when:\n\n- a user taps the checkmark button under the follow category button of the Clips Player\n- a user taps the follow button at the top right of the Followable Category screen and the category was followed\n\n### Followable Category Tapped\n\nThis event is recorded when:\n\n- a user taps the follow category button of the Clips Player to open the Followable Category screen\n- a user swipes left from the right edge of the screen on a Clip with a Followable Category and opens the Followable Category screen\n\n### Enable Captions\n\nThis event is recorded when:\n\n- a user taps the button to enable Closed Captions in the Clips Player\n\n### Disable Captions\n\nThis event is recorded when:\n\n- a user taps the button to disable Closed Captions in the Clips Player\n\n### Muted Clip\n\nThis event is recorded when:\n\n- A user mutes a Clip by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n### Unmuted Clip\n\nThis event is recorded when:\n\n- A user unmutes a Clip by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n### Followable Category Limit Shown\n\nThis event is recorded when:\n\n- the alert dialogue box associated with the Followable Category Limit is shown\n\nWhenever a Followable Category Limit Shown event occurs, additional event data specific to this event includes `followableCategoryLimitDialogue`, `followableCategoryLimitActionText`, and `followableCategoryLimitActionUrl`.\n\n### Followable Category Limit Action Button Tapped\n\nThis event is recorded when:\n\n- a user taps on the customisable action button in the Followable Category Limit Dialogue Box\n\nWhenever a Followable Category Limit Action Button Tapped event occurs, additional event data specific to this event includes `followableCategoryLimitDialogue`, `followableCategoryLimitActionText`, and `followableCategoryLimitActionUrl`.\n\n### Followable Category Limit Dismissed\n\nThis event is recorded when:\n\n- a user dismisses the Followable Category Limit Dialogue Box by tapping the cancel action button\n\nWhenever a Followable Category Limit Dismissed event occurs, additional event data specific to this event includes `followableCategoryLimitDialogue`, `followableCategoryLimitActionText`, and `followableCategoryLimitActionUrl`.\n\n## List Tile Events\n\n### Tile Visible\n\nThis event is recorded when a Story or Clip tile becomes visible in a Storyteller list row or grid.\n\nIt is recorded in the following scenarios:\n\n- when list data is rendered and one or more tiles are visible\n- when a user scrolls and new tiles become visible\n- when a list reloads or refreshes with updated content and visible tiles are re-evaluated\n\nThis event is not recorded again while the same tile remains continuously visible, and it is not recorded just because the app returns from the background or the Story/Clip Player is dismissed if the same visible tiles remain and the list did not reload or scroll.\n\nWhenever a Tile Visible event occurs, additional event data specific to this event includes `tileIndex`. Story tile events include `storyId`, `storyTitle`, `categories`, and `context` when available. Clip tile events include `clipId`, `clipTitle`, `collection`, `categories`, and `context` when available.\n\n## Card Events\n\nThe following properties are included in all Card-related events:\n\n- `cardActionType`\n- `cardActionUrl`\n- `cardAspectRatio`\n- `cardBackgroundType`\n- `cardCollectionId`\n- `cardId`\n- `cardIndex`\n- `cardSubtitle`\n- `cardTitle`\n- `categories`\n- `categoryDetails`\n- `hasButton`\n- `isLive`\n- `context`\n- `actionLinkId`\n- `isMuted` when the Card audio state is known. Image and non-video Card events report `nil`.\n\nThe following additional properties are included on specific card video events:\n\n- `videoStartReason` on `Card Video Started`\n- `durationViewed` on `Card Video Heartbeat` and `Card Video Completed`\n- `audioToggleFrom` and `audioToggleTo` on `Card Audio Toggled`\n\n### Card Viewed\n\nThis event is recorded when:\n\n- a Storyteller Card appears on screen, either by scrolling to it or opening a view where its visible\n\n### Card Tapped\n\nThis event is recorded when:\n\n- a user taps on the Storyteller Card view\n\n### Card Video Started\n\nThis event is recorded when:\n\n- a video Storyteller Card begins video playback\n- a visible video Storyteller Card naturally loops and starts the next playback cycle\n\nThis event is only emitted for video cards.\n\nWhenever a Card Video Started event occurs, additional event data specific to this event includes `videoStartReason`.\n\nFor Card Video Started, `videoStartReason` is `natural` for the first visible playback start of the current Card session and `loop` when the same visible Card naturally restarts after a completed loop.\n\n### Card Video Heartbeat\n\nThis event is recorded when:\n\n- a visible video Storyteller Card reaches 5 seconds, 10 seconds, 15 seconds, and so on of active playback within the current loop\n\nThis event is only emitted for video cards.\n\nWhenever a Card Video Heartbeat event occurs, additional event data specific to this event includes `durationViewed`.\n\nFor Card Video Heartbeat, `durationViewed` is reported in milliseconds, counts active playback only, accumulates through pauses, buffering, backgrounding, and other interruptions within the same loop, and resets when the video starts a new loop.\n\n### Card Video Completed\n\nThis event is recorded when:\n\n- a visible video Storyteller Card reaches a natural end-of-item loop boundary\n\nThis event is only emitted for video cards.\n\nWhenever a Card Video Completed event occurs, additional event data specific to this event includes `durationViewed`.\n\nFor Card Video Completed, `durationViewed` is the active playback duration of the completed loop in milliseconds.\n\n### Card Audio Toggled\n\nThis event is recorded when:\n\n- a user toggles audio for an active video Storyteller Card\n\nThis event is only emitted for video Cards where audio can be controlled. It is not emitted for no-audio Cards, behavior-locked muted Cards, inactive Cards, or interruption-forced mutes.\n\nWhenever a Card Audio Toggled event occurs, additional event data specific to this event includes `audioToggleFrom`, `audioToggleTo`, and `isMuted`. `isMuted` reflects the resulting state after the toggle.\n\n## Ad Events\n\nAd-related events include both ad interaction events (for example `OpenedAd`, `DismissedAd`) and paid ad operational events (for example `AdOpportunity`, `AdRequested`). Not every field is present on every ad event type.\n\nThe following properties may be included in ad-related events:\n\n- `adFormat`\n- `adId`\n- `adIndex`\n- `adPlacement`\n- `adResponseIdentifier`\n- `adStrategy`\n- `adType`\n- `adUnitId`\n- `advertiserName`\n- `airplayEnabled`\n- `categories`\n- `categoryDetails`\n- `clipActionText`\n- `clipActionType`\n- `clipHasAction`\n- `contentLength`\n- `currentCategory`\n- `isMuted`\n- `pageActionText`\n- `pageActionType`\n- `pageActionUrl`\n- `pageHasAction`\n- `searchTerm`\n- `context`\n\nFor Ad Opportunity events, additional fields include:\n\n- `playerSessionId`\n- `adSlotType`\n\nFor Ad Requested events, additional fields include:\n\n- `playerSessionId`\n- `adRequestId`\n- `adSlotType`\n- `adUnitId`\n- `adSource`\n\nFor Ad Loaded events, additional fields include:\n\n- `playerSessionId`\n- `adRequestId`\n- `adSlotType`\n- `adUnitId`\n- `adSource`\n- `adSourceName`\n- `adSourceId`\n- `adSourceInstanceName`\n- `adSourceInstanceId`\n- `adAdapterLatencyMillis`\n- `adMediationGroupName`\n- `adMediationAbTestName`\n- `adMediationAbTestVariant`\n\nFor Ad Failed To Load events, additional fields include:\n\n- `playerSessionId`\n- `adRequestId`\n- `adSlotType`\n- `adUnitId`\n- `adSource`\n- `adErrorCode`\n- `adErrorDomain`\n- `adErrorMessage`\n- `adAdapterLatencyMillis`\n\nFor Ad Paid events, additional fields include:\n\n- `playerSessionId`\n- `adRequestId`\n- `adSlotType`\n- `adUnitId`\n- `adSource`\n- `adSourceName`\n- `adSourceId`\n- `adSourceInstanceName`\n- `adSourceInstanceId`\n- `adAdapterLatencyMillis`\n- `adValueMicros`\n- `adCurrencyCode`\n- `adValuePrecision`\n\nFor Story Ad events specifically, additional common fields include:\n\n- `storyId`\n- `pageId`\n- `pageActionText`\n- `pageActionType`\n- `pageActionUrl`\n- `pageHasAction`\n- `pageType`\n- `storyPlaybackMode`\n\nFor Clip Ad events specifically, additional common fields include:\n\n- `clipId`\n- `clipActionType`\n- `clipHasAction`\n- `clipActionText`\n- `clipActionUrl`\n- `clipFeedType`\n- `clipIndex`\n- `collection`\n- `collectionClipCount`\n- `loopsViewed`\n\n### Ad Opportunity\n\nThis event is recorded when the SDK reaches an eligible ad slot and is about to request an ad.\n\nThis can happen for:\n\n- full-screen ads in Stories\n- full-screen ads between clips\n- bottom banner ads in the Clips player\n\nWhenever an Ad Opportunity event occurs, additional event data specific to this event includes `playerSessionId` and `adSlotType`.\n\n`AdOpportunity` also includes the same contextual ad fields as `OpenedAd` when they are available at opportunity time (for example `storyId`, `pageId`, `storyPlaybackMode`, `categories`, `currentCategory`, `pageActionType`, `pageHasAction`, `pageActionText`, `pageActionUrl`, `clipId`, `clipActionType`, `clipHasAction`, `clipActionText`, `clipActionUrl`).\n\nSome differences between `AdOpportunity` and `OpenedAd` are expected by design because they are captured at different moments: `AdOpportunity` is a slot-time snapshot (before the ad request), while `OpenedAd` is captured when the rendered ad is opened.\n\n### Ad Requested\n\nThis event is recorded when the SDK initiates an Ad request. This event is emitted only for Google Ad sources (GAM and AdMob).\n\nThis can happen for:\n\n- full-screen ads in Stories\n- full-screen ads between clips\n- bottom banner ads in the Clips player\n\nWhenever an Ad Requested event occurs, additional event data specific to this event includes `playerSessionId`, `adRequestId`, `adSlotType`, `adUnitId`, and `adSource`.\n\nFor GAM and AdMob integrations supplied by Storyteller, `adUnitId` is the exact unit used for that request attempt. If AdMob falls back between native and banner formats, each concrete attempt emits its own `AdRequested` event with the corresponding unit and the same `adRequestId`.\n\nIf a Google module fails before it can resolve a unit or start a concrete provider load, the SDK preserves the request/failure event pair with `adUnitId` set to `nil`.\n\n### Ad Loaded\n\nThis event is recorded when the SDK successfully loads an ad and considers it available for rendering (even if it is not ultimately shown). This event is emitted only for Google Ad sources (GAM and AdMob).\n\nThis can happen for:\n\n- full-screen ads in Stories\n- full-screen ads between clips\n- bottom banner ads in the Clips player\n\nWhenever an Ad Loaded event occurs, additional event data specific to this event includes `playerSessionId`, `adRequestId`, `adSlotType`, `adUnitId`, `adSource`, `adSourceName`, `adSourceId`, `adSourceInstanceName`, `adSourceInstanceId`, `adAdapterLatencyMillis`, `adMediationGroupName`, `adMediationAbTestName`, and `adMediationAbTestVariant`.\n\n`adUnitId` identifies the successful unit. Response metadata takes precedence when it differs from the requested unit.\n\n### Ad Failed To Load\n\nThis event is recorded when the SDK fails to load an Ad request (including no-fill). This event is emitted only for Google Ad sources (GAM and AdMob).\n\nThis can happen for:\n\n- full-screen ads in Stories\n- full-screen ads between clips\n- bottom banner ads in the Clips player\n\nWhenever an Ad Failed To Load event occurs, additional event data specific to this event includes `playerSessionId`, `adRequestId`, `adSlotType`, `adUnitId`, `adSource`, `adErrorCode`, `adErrorDomain`, `adErrorMessage`, and `adAdapterLatencyMillis`.\n\n`adUnitId` identifies the concrete unit used by the failed request attempt. It is `nil` when the module failed before resolving a unit or starting the provider load.\n\n### Ad Paid\n\nThis event is recorded when the SDK receives impression-level paid revenue info for an Ad from Google Ad sources.\n\nThis can happen for:\n\n- full-screen ads in Stories\n- full-screen ads between clips\n- bottom banner ads in the Clips player\n\nWhenever an Ad Paid event occurs, additional event data specific to this event includes `playerSessionId`, `adRequestId`, `adSlotType`, `adUnitId`, `adSource`, `adSourceName`, `adSourceId`, `adSourceInstanceName`, `adSourceInstanceId`, `adAdapterLatencyMillis`, `adValueMicros`, `adCurrencyCode`, and `adValuePrecision`.\n\n### Ad Session Summary\n\nThis event is recorded once when a root Storyteller player session ends (Clips or Stories). If a prior session was persisted without being ended cleanly, this summary can also be emitted on the next SDK initialize. The session spans app background/foreground transitions and is not restarted until the root player session ends.\n\nThe summary aggregates paid ads activity for that player session:\n\n- `playerSessionId`\n- `adSessionOpportunitiesCount`\n- `adSessionRequestsCount`\n- `adSessionLoadsCount`\n- `adSessionFailedToLoadCount`\n- `adSessionPaidCount`\n- `adSessionRevenueMicros` (optional)\n- `adSessionCurrencyCode` (optional)\n\n`adSessionRevenueMicros` and `adSessionCurrencyCode` are only included when all paid events in that session can be represented as a single currency with complete paid data.\n\nWhenever an Ad Session Summary event occurs, additional event data specific to this event includes `playerSessionId`, `adSessionOpportunitiesCount`, `adSessionRequestsCount`, `adSessionLoadsCount`, `adSessionFailedToLoadCount`, `adSessionPaidCount`, `adSessionRevenueMicros` (optional), and `adSessionCurrencyCode` (optional).\n\n`adUnitId` is `nil` for `AdSessionSummary` because a session can aggregate requests across multiple ad units.\n\n### Opened Ad\n\n#### Stories\n\nThis event is recorded when:\n\n- an ad is loaded because the previous story finished\n- a user swipes left on a story to go to the next story and an ad appears\n- a user swipes right on a story to go to the previous story and an ad appears\n\nWhenever an Opened Ad event occurs, additional event data specific to this event includes `adView` and `openedReason`.\n\n#### Clips\n\nThis event is recorded when:\n\n- a user swipes up on a clip to go to the next clip and an ad should appear next\n- a user swipes down on a clip to go to the previous clip and an ad should appear next\n- an ad completes a loop and begins playing again from the start\n\nInformation about Ad View is only sent to client delegates on an OpenedAd event.\n\nWhenever an Opened Ad event occurs, additional event data specific to this event includes `adView` and `openedReason`.\n\n### Dismissed Ad\n\n#### Stories\n\nThis event is recorded when a user:\n\n- taps close to dismiss the ad\n- swipes down to dismiss the ad\n- taps back on their device UI to dismiss the ad (Android only)\n- taps to skip the ad if the ad is the last page in the current set of stories\n- swipes left on the ad to skip it if the ad is the last page in the current set of stories\n- completes the ad if the ad is the last page in the current set of stories\n\nWhenever a Dismissed Ad event occurs, additional event data specific to this event includes `durationViewed`, `dismissedReason` and `pagesViewedCount`.\n\n#### Clips\n\nThis event is recorded when a user:\n\n- taps the back button to exit the clips player when an ad is being shown\n\nWhenever a Dismissed Ad event occurs, additional event data specific to this event includes `durationViewed`, and `clipsViewed`.\n\n### Skipped Ad\n\n#### Stories\n\nThis event is recorded when a user:\n\n- swipes left to go to the next story before completing the current ad\n- taps to go to the next page on an ad before completing the current ad\n\n#### Clips\n\nThis event is recorded when:\n\n- a user swipes up to go to the next clip\n- a user swipes down to go the previous clip\n\n### Ad Action Button Tapped\n\n#### Stories\n\nThis event is recorded when a user:\n\n- swipes up on an ad to open a link\n- taps on the swipe up element of an ad to open a link\n\n#### Clips\n\nThis event is recorded when a user:\n\n- taps the action button at the bottom of an ad displayed in clips\n- swipes left on a clip to open the relevant action\n\n### Finished Ad\n\n#### Stories\n\nThis event is recorded at the same time as Dismissed Ad, Skipped Ad and Viewed Ad Page Complete and gives an easier way to determine when an ad finishes for any reason.\n\nWhenever a Finished Ad event occurs, additional event data specific to this event includes `adView`.\n\n#### Clips\n\nThis event is recorded at the same time as DismissedAd, or SkippedAd.\n\nWhenever a Finished Ad event occurs, additional event data specific to this event includes `adView`.\n\n### Paused Ad\n\n#### Stories\n\nThis event is recorded when a user pauses a page within an ad by pressing and holding on the page.\n\n#### Clips\n\nThis event is recorded when a user pauses a clip which is an ad by tapping the screen. It does not fire when a clip is paused automatically for sharing or following an action.\n\n### Resumed Ad\n\n#### Stories\n\nThis event is recorded when a user resumes playing a page within an ad by releasing their long press which paused the ad.\n\n#### Clips\n\nThis event is fired when a clip which is an ad is paused and a user taps the screen to resume playback. It does not fire when a clip is resumed automatically.\n\n### Viewed Ad Page First Quartile\n\nThis event is recorded when a user reaches 1/4 of the way through the duration of a page or clip which is an ad.\n\nFor clip ads (which loop), it fires for each loop of the clip.\n\n### Viewed Ad Page Midpoint\n\nThis event is recorded when a user reaches halfway through the duration of a page or clip which is an ad.\n\nFor clip ads (which loop), it fires for each loop of the clip.\n\n### Viewed Ad Page Third Quartile\n\nThis event is recorded when a user reaches 3/4 of the way through the duration of a page or clip which is an ad.\n\nFor clip ads (which loop), it fires for each loop of the clip.\n\n### Viewed Ad Page Complete\n\nThis event is recorded when a user reaches the end of the duration for a page or clip which is an ad.\n\nFor clip ads (which loop), it fires for each loop of the clip.\n\n### Muted Ad\n\nThis event is recorded when:\n\n- A user mutes an Ad (in either Stories or Clips) by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n### Unmuted Ad\n\nThis event is recorded when:\n\n- A user unmutes an Ad (in either Stories or Clips) by toggling the mute button, adjusting device volume controls, or using the UI mute button\n\n## Playback Events\n\nThe following properties are included in all Playback-related events:\n\n- `isMuted`\n- `pageActionText`\n- `pageActionUrl`\n- `pageHasAction`\n- `pageId`\n- `pageIndex`\n- `pageTitle`\n- `pageType`\n- `storyDisplayTitle`\n- `storyId`\n- `storyIndex`\n- `storyPlaybackMode`\n- `storyTitle`\n- `context`\n\n### Ready to Play\n\nThis event is called once per video page at the point when the video player has been loaded.\n\n### Media Started\n\nThis event is called once per video page at the point when the video starts to play for the first time.\n\n### Buffering Started\n\nThis event is called on video pages whenever the video starts to buffer.\n\nWhenever a Buffering Started event occurs, additional event data specific to this event includes `isInitialBuffering`.\n\n### Buffering Ended\n\nThis event is called on video pages whenever the video finishes buffering.\n\n> Note: There should be at most one Ready to Play event and one Media Started event for every page. There may be multiple Buffering Started/Buffering Ended pairs of events for an individual page. There may not always be a Buffering Ended event for every Buffering Started event as the user may choose to exit the page during buffering.\n\nWhenever a Buffering Ended event occurs, additional event data specific to this event includes `isInitialBuffering` and `timeSinceBufferingBegan`.\n\n## Sheet Events\n\nThe following properties are included in all Sheet-related events:\n\n- `actionText`\n- `captionsEnabled`\n- `categories`\n- `categoryDetails`\n- `clipActionText`\n- `clipActionType`\n- `clipActionUrl`\n- `clipFeedType`\n- `clipHasAction`\n- `clipId`\n- `clipIndex`\n- `clipTitle`\n- `collection`\n- `collectionClipCount`\n- `containerTitle`\n- `currentCategory`\n- `isLive`\n- `isMuted`\n- `pageActionText`\n- `pageActionType`\n- `pageActionUrl`\n- `pageHasAction`\n- `pageId`\n- `pageIndex`\n- `pageTitle`\n- `pageType`\n- `searchFilter`\n- `searchSort`\n- `searchTerm`\n- `sheetId`\n- `sheetSize`\n- `sheetTitle`\n- `storyId`\n- `storyIndex`\n- `storyPageCount`\n- `storyTitle`\n- `context`\n\n### Opened Sheet\n\nThis event is recorded when a user opens a Sheet.\n\nWhenever an Opened Sheet event occurs, additional event data specific to this event includes `openedReason`.\n\n### Dismissed Sheet\n\nThis event is recorded when a user closes a Sheet.\n\n## Search Events\n\nThe following properties are included in all Search-related events:\n\n- `categories`\n- `categoryDetails`\n- `currentCategory`\n- `isSuggestion`\n- `searchFilter`\n- `searchFrom`\n- `searchSort`\n- `searchTerm`\n\nWhen search is opened from a Story context, additional properties include:\n\n- `pageActionText`\n- `pageActionUrl`\n- `pageHasAction`\n- `pageId`\n- `pageIndex`\n- `pageTitle`\n- `pageType`\n- `storyDisplayTitle`\n- `storyId`\n- `storyIndex`\n- `storyPageCount`\n- `storyPlaybackMode`\n- `storyReadStatus`\n- `storyTitle`\n- `context`\n\nWhen search is opened from a Clip context, additional properties include:\n\n- `clipActionText`\n- `clipActionUrl`\n- `clipHasAction`\n- `clipId`\n- `clipIndex`\n- `clipTitle`\n- `collection`\n- `context`\n\n### Opened Search\n\nThe openedSearch event is recorded when:\n\n- A user taps on Search from a Story within the Story player\n- A user taps on Search from a Clip within the Clip player\n- The `Storyteller.shared.openSearch()` function is called\n\n### Dismissed Search\n\nThe dismissedSearch event is recorded when a user taps the 'X' button to exit the Search interface.\n\nWhenever an Dismissed Search event occurs, additional event data specific to this event includes `dismissedReason`.\n\n### Performed Search\n\nThe performedSearch event is recorded when:\n\n- A user taps the 'Search' icon after entering a term in the Search bar (whether manually or by tapping the 'arrow' icon beside a Search suggestion to populate the search bar)\n- A user taps the 'Search' icon beside a Search suggestion. The Search is then performed with the suggestion as the term.\n- A user taps 'Apply filters' from the filters interface.\n\n### Opened Filters\n\nThe openedFilters event is recorded when, after a user has performed as Search, they press the 'Filter' icon to bring up the filter interface.\n\n> Note: That filters can only be applied after the initial search has been performed.\n\n### Dismissed Filters\n\nThis event is recorded when a user, after calling up the 'Filters' interface, swipes down to exit the interface without applying any.\n\n### Used Suggestion\n\nThe usedSuggestion event is recorded when:\n\n- A user taps the 'arrow' icon beside a Search suggestion to populate the Search bar. This does not trigger any other event, and the user may amend the Search bar input before performing a Search.\n- A user taps the 'Search' icon beside a Search suggestion. This simultaneously triggers a PerformedSearch event, above.\n\nWhenever a Used Suggestion event occurs, additional event data specific to this event includes `initialInput`.\n\n## Event Data\n\nFor each event, data is returned with details about the story and page involved as well as some extra properties with more information about what the user has done. The data is returned as a `StorytellerUserActivityData` class with the following properties:\n\n### Story ID\n\nThe `storyId: String?` is the ID of the story for which the event occurred.\n\n### Story Title\n\nThe `storyTitle: String?` is the title of the story for which the event occurred.\n\n### Story Display Title\n\nThe `storyDisplayTitle: String?` is the display title of the Story for which the event occurred.\n\n### Story Index\n\nThe `storyIndex: Int?` is the index of the story for which the event occurred in the row from which it was opened at the point it was opened - this is only included on `OpenedStory` events.\n\n> Note: This value is 1-based.\n\n### Story Page Count\n\nThe `storyPageCount: Int?` is the number of pages in the story.\n\n### Story Read Status\n\nThe `storyReadStatus: String?` is whether the story was read or unread at the point the story was opened - this is only included on `OpenedStory` events.\n\n> Note: This will either be `read` or `unread`.\n\n### Page ID\n\nThe `pageId: String?` is the ID of the page for which the event occurred.\n\n### Page Index\n\nThe `pageIndex: Int?` is the index of the page in the story for which the event occurred.\n\n> Note: This value is 1-based.\n\n### Page Type\n\nThe `pageType: String?` is the type of the page associated with the event. This can have the value `image`, `video` or `poll`.\n\n### Story Playback Mode\n\nThe `storyPlaybackMode: String?` value states if the story was opened during the list or in the single story mode (Storyteller static method.) This is included for all events. The values for this are either `list` or `singleStory`.\n\n### Page Has Action\n\nThe `pageHasAction: Bool?` value states whether the page associated with the event contains an action.\n\n### Page Action Type\n\nThe `pageActionType: String?` is the type of the action on the page.\n\n### Page Action Text\n\nThe `pageActionText: String?` is the text call to action if the page has an action.\n\n### Page Action URL\n\nThe `pageActionUrl: String?` is the URL for the link if the page has an action.\n\n### Action Link ID\n\nThe `actionLinkId: String?` is the unique identifier of the action associated with the current story page, clip or card. This is not included for Ad events.\n\n### Opened Reason\n\nThe `openedReason: String?` value states how the user opened a Story or Clip. The possible values for this are:\n- `storyListTap`: The user tapped the Story in the Story row.\n- `clipListTap`: The user tapped the Clip in a Clip list.\n- `deepLink`: `openStory` or `openPage` was called to open the Story.\n- `swipe`: The user swiped left or right to change the current Story.\n- `automaticPlayback`: The user completed the previous Page.\n- `card`: The user taps on a Card.\n- `clipActionButton`: The user clicked on an action button in the Clips player.\n- `pageActionButton`: The user clicked on the action button in the Story player.\n- `tap`: The user tapped on the next or previous Story Page to navigate to this page.\n- `instanceMethod`: `Storyteller.shared.openStory(id:)` or `Storyteller.shared.openPage(id:)` was called to open a Story or a Page.\n- `loop`: The user completes a loop of a Clip naturally or by scrubbing to the end of the Clip's duration.\n\n`openedReason` is only included on `OpenedStory`, `OpenedClip`, `OpenedPage`, `StoryInstructionsScreenViewed`, `CompletedLoop`, `OpenedAd` and `OpenedSheet` events.\n\n### Video Start Reason\n\nThe `videoStartReason: String?` value states why a Card video start was emitted. The possible values are `natural` (the first visible playback start for the Card session) and `loop` (the Card video completed a loop and restarted while still visible).\n\n`videoStartReason` is only included on `CardVideoStarted` events.\n\n### Dismissed Reason\n\nThe `dismissedReason: String?` value states the way the user dismissed a story or clip. The possible values for this are `closeButtonTapped` (the user tapped close to dismiss the story); `swipedDown` (the user swiped down to dismiss the story); `swipedFirstStory` (the user swiped the first story to dismiss it); `swipedFinalStory` (the user swiped the final story to dismiss it); `skippedFinalPage` (the user tapped to skip the final page of the final story); `completedFinalPage` (the user completed the final page of the final story) and `backButtonTapped` (the user tapped the back button to dismiss the clip).\n\n`dismissedReason` is only included on `DismissedStory` and `DismissedClip` events.\n\n### Duration Viewed\n\nThe `durationViewed: Float?` is the duration the user viewed the story or clip for in milliseconds. This is measured from the most recent `OpenedStory` or `OpenedClip` event with an Opened Reason of `storyRowTap`, `deepLink`, `card`, `pageActionButton`, `clipActionButton` or `clipsListTap`.\n\nThis timer is reset after any `DismissedStory` or `DismissedClip` events.\n\nFor `FinishedClip`, Duration Viewed is the duration the user viewed the clips player for in milliseconds. This is measured from the most recent `OpenedClip` event with an Opened Reason of `swipe`.\n\nFor `CardVideoHeartbeat` and `CardVideoCompleted`, `durationViewed` is the active playback duration for the current card-video loop in milliseconds. It accumulates through pauses, buffering, backgrounding, and other interruptions within the same loop, and resets when a new loop starts.\n\n### Audio Toggle From / To\n\nThe `audioToggleFrom: String?` and `audioToggleTo: String?` values state the previous and resulting Cards audio state for `CardAudioToggled` events. Possible values are `muted` and `unmuted`.\n\n### Pages Viewed Count\n\nThe `pagesViewedCount: Int?` is the total number of pages a user has viewed since the most recent `OpenedStory` event with an Opened Reason of `storyRowTap`, `pageActionButton`, `clipActionButton`, `card` or `deepLink`. This count is reset after any `DismissedStory` events.\n\n### Content Length\n\nThe `contentLength: Int?` is the total duration of the page content in seconds.\n\n### Share Method\n\nThe `shareMethod: String?` is the component name of the app which the user has selected for sharing.\n\n### Advertisers Name\n\nThe `advertiserName: String?` is the name of the advertiser for a particular ad. This is only included for ad events.\n\n### Ad ID\n\nThe `adId: String?` is the ad ID if an event is associated with an ad.\n\n### Ad View\n\nThe `adView: View?` is the view the ad is rendered in. This is only included for `OpenedAd` and `FinishedAd` events.\n\n### Ad Type\n\nThe `adType: String?` is the type of component on which the ad is displayed. This can have values `stories` or `clips`.\n\n### Ad Format\n\nThe `adFormat: String?` represents the format of the Ad that was displayed. Possible values can be `customNative`, `native`, `banner`.\n\n### Ad Placement\n\nThe `adPlacement: String?` represents the placement of the ad. It can be either `Between Stories`, `Between Pages` or `Between Clips`. This is only included for ad events.\n\nFor Story ad events, `AdOpportunity` and `OpenedAd` use the same placement naming (`Between Stories` / `Between Pages`).\n\n### Ad Strategy\n\nThe `adStrategy: String?` represents the strategy used to display the ads. It can have the following values: `Between Stories`, `Between Pages`, `Between Stories and Pages`, `Between Clips`.\n\n### Ad Response Identifier\n\nThe `adResponseIdentifier: String?` represents the response identifier attached to the ad that was received from the ad provider. Used for debugging ad targeting.\n\n### Ad Index\n\nThe `adIndex: Int?` represents the order of the Ad within the displayed Ads in a Story or Clip collection (1 for the first Ad, 2 for the second, etc.). This field is included in all ad-related events.\n\n### Player Session ID\n\nThe `playerSessionId: String?` is a unique identifier for the current root player session. This is included on `AdOpportunity`, `AdRequested`, `AdLoaded`, `AdFailedToLoad`, `AdPaid`, and `AdSessionSummary` events.\n\n### Ad Request ID\n\nThe `adRequestId: String?` is a unique identifier that correlates an ad request chain. This is included on `AdRequested`, `AdLoaded`, `AdFailedToLoad`, and `AdPaid` events. Concrete native/banner fallback attempts share the same identifier.\n\n### Ad Slot Type\n\nThe `adSlotType: String?` indicates the type of ad slot for `AdOpportunity`, `AdRequested`, `AdLoaded`, `AdFailedToLoad`, and `AdPaid` events. Possible values are `fullScreen` and `bottomBanner`.\n\n### Ad Unit ID\n\nThe `adUnitId: String?` is the exact ad unit identifier when it is known. It is available on paid ad operational events and is retained on rendered ad interaction events such as `OpenedAd`, `DismissedAd`, quartile events, and `FinishedAd`.\n\nFor Storyteller GAM and AdMob integrations, the SDK records the unit immediately before each concrete request attempt. For GAM VAST ads, it uses the final `iu` tag parameter after client overrides. Host-supplied custom modules can provide the value through `StorytellerAd.adUnitId`.\n\n`adUnitId` is `nil` for `AdOpportunity` because provider and unit selection have not occurred yet, and for `AdSessionSummary` because the event aggregates multiple requests. It can also be `nil` for Storyteller First Party Ads, direct VAST ads, or custom modules that do not supply a unit.\n\n### Ad Source\n\nThe `adSource: String?` is the high-level source for ad events. Supported values include `storyteller` for Storyteller First Party Ads, `gam`, `admob`, and custom source values provided by integrating-app modules via `StorytellerModule.adSource`. This is included on all ad-related events. For `AdOpportunity`, `adSource` is always `nil` because the event is emitted before ad module resolution. For other ad events, `adSource` may still be `nil` when the source cannot be resolved.\n\n### Ad Mediation Group Name\n\nThe `adMediationGroupName: String?` is the mediation group name returned by the ad provider when available. This is included on `AdLoaded` events when available.\n\n### Ad Mediation Ab Test Name\n\nThe `adMediationAbTestName: String?` is the mediation A/B test name returned by the ad provider when available. This is included on `AdLoaded` events when available.\n\n### Ad Mediation Ab Test Variant\n\nThe `adMediationAbTestVariant: String?` is the mediation A/B test variant returned by the ad provider when available. This is included on `AdLoaded` events when available.\n\n### Ad Adapter Latency Millis\n\nThe `adAdapterLatencyMillis: Int?` is the elapsed time in milliseconds for the concrete ad request attempt that produced the result. When native/banner fallback occurs, load, failure, and paid events use the final attempt's latency. This is included on `AdLoaded`, `AdFailedToLoad`, and `AdPaid` events.\n\n### Ad Error Code\n\nThe `adErrorCode: Int?` is the numeric error code reported by the ad provider. This is included on `AdFailedToLoad` events.\n\n### Ad Error Domain\n\nThe `adErrorDomain: String?` is the error domain reported by the ad provider. This is included on `AdFailedToLoad` events.\n\n### Ad Error Message\n\nThe `adErrorMessage: String?` is the error description reported by the ad provider. This is included on `AdFailedToLoad` events.\n\n### Ad Value Micros\n\nThe `adValueMicros: Int?` is the paid value in micros (1,000,000 micros = 1 unit of currency). This is only included on `AdPaid` events.\n\n### Ad Currency Code\n\nThe `adCurrencyCode: String?` is the currency code for the paid value (ISO 4217). This is only included on `AdPaid` events.\n\n### Ad Value Precision\n\nThe `adValuePrecision: String?` indicates how precise the paid value is. Possible values are `UNKNOWN`, `ESTIMATED`, `PUBLISHER_PROVIDED`, and `PRECISE`. This is only included on `AdPaid` events.\n\n### Ad Session Opportunities Count\n\nThe `adSessionOpportunitiesCount: Int?` is the total number of ad opportunities tracked in the player session. This is only included on `AdSessionSummary` events.\n\n### Ad Session Requests Count\n\nThe `adSessionRequestsCount: Int?` is the total number of ad-module request attempts initiated in the player session. Native/banner fallback attempts are counted separately, and a module failure before provider load counts once, so this value can exceed the number of ad opportunities. This is only included on `AdSessionSummary` events.\n\n### Ad Session Loads Count\n\nThe `adSessionLoadsCount: Int?` is the total number of successful ad loads in the player session. This is only included on `AdSessionSummary` events.\n\n### Ad Session Failed To Load Count\n\nThe `adSessionFailedToLoadCount: Int?` is the total number of ad load failures in the player session. This is only included on `AdSessionSummary` events.\n\n### Ad Session Paid Count\n\nThe `adSessionPaidCount: Int?` is the total number of paid callbacks received in the player session. This is only included on `AdSessionSummary` events.\n\n### Ad Session Revenue Micros\n\nThe `adSessionRevenueMicros: Int?` is the aggregated session paid value in micros. This is only included on `AdSessionSummary` events when all paid callbacks in the session use one currency and include complete paid data.\n\n### Ad Session Currency Code\n\nThe `adSessionCurrencyCode: String?` is the ISO 4217 currency code associated with `adSessionRevenueMicros`. This is only included on `AdSessionSummary` events when all paid callbacks in the session use one currency and include complete paid data.\n\n### Is Initial Buffering\n\nThe `isInitialBuffering: Boolean?` value is returned if the buffering happens at the start of playback for that page. This is only included for `BufferingStarted` and `BufferingEnded` events.\n\n### Time Since Buffering Began\n\nThe `timeSinceBufferingBegan: TimeInterval?` value is the duration the current buffering lasted for in milliseconds. This is only included for `BufferingEnded` events.\n\n### Categories\n\nThe `categories: [String]?` value is the list of categories assigned to the story or clip for which the event occurred. This is included on `OpenedStory` and `TileVisible` events, and may be included on other story, clip, ad, card, search, or sheet events when category context is available.\n\n### Poll Answer\n\nThe `pollAnswerId: String?` is the ID of the answer the user selected when voting. This is only included on `VotedPoll` events.\n\n### Trivia Quiz ID\n\nThe `triviaQuizId: String?` is the ID of the trivia quiz that was completed or answered. This is only included on `TriviaQuizQuestionAnswered` and `TriviaQuizCompleted` events.\n\n### Trivia Quiz Title\n\nThe `triviaQuizTitle: String?` is the title of the trivia quiz that was completed or answered. This is only included on `TriviaQuizQuestionAnswered` and `TriviaQuizCompleted` events.\n\n### Trivia Quiz Score\n\nThe `triviaQuizScore: Int?` value is the score of the trivia quiz that was completed. This is only included on `TriviaQuizCompleted` events.\n\n### Trivia Quiz Question ID\n\nThe `triviaQuizQuestionId: String?` is the ID of the trivia quiz question which was answered. This is only included on `TriviaQuizQuestionAnswered` events.\n\n### Trivia Quiz Answer ID\n\nThe `triviaQuizAnswerId: String?` is the ID of the selected trivia quiz answer. This is only included on `TriviaQuizQuestionAnswered` events.\n\n### Clip ID\n\nThe `clipId: String?` is the ID of the clip for which the event occurred.\n\n### Clip Title\n\nThe `clipTitle: String?` is the title of the clip for which the event occurred.\n\n### Clip Index\n\nThe `clipIndex: Int?` is the index of the clip in the row or grid at the point it was selected or the index of the clip in the player inside the original row or grid. For Ad events, clip index refers to the index of the clip before the Ad.\n\n### Tile Index\n\nThe `tileIndex: Int?` is the index of the Story or Clip tile in the row or grid at the point it became visible. This is only included on `TileVisible` events.\n\n> Note: This value is 1-based.\n\n### Clip Collection Count\n\nThe `clipCollectionCount: Int?` is the total number of clips in the collection being viewed.\n\n### Clip Feed Type\n\nThe `clipFeedType: String?` indicates the type of clip feed being viewed. Possible values are `default`, `forYou`, and `following`.\n\n### Clips Viewed\n\nThe `clipsViewed: Int?` value is the total number of clips a user has viewed since the most recent OpenedClip event with an Opened Reason of `clipListTap`, `pageActionButton`, `card`, `clipActionButton` or `deepLink`. This count should be reset after any DismissedClip events.\n\n### Loops Viewed\n\nThe `loopsViewed: Int?` is for DismissedClip, the total number of loops (plays of an individual clip) a user has viewed since the most recent OpenedClip event with an Opened Reason of `clipListTap`, `pageActionButton`, `card`, `clipActionButton` or `deepLink`.\n\nThis count should be reset after any DismissedClip events. For FinishedClip, the total number of loops.\n\n### Is Live\n\nThe `isLive: Bool?` indicates whether a Clip, Story, or Card is currently being broadcast in real-time and is therefore \"Live\".\n\n### Airplay Enabled\n\nThe `airplayEnabled: Bool?` indicates whether the device is currently using AirPlay for audio/video output when the event occurred.\n\n### Clip Has Action\n\nThe `clipHasAction: Bool?` value is whether the clip associated with the event contains a primary action.\n\n### Clip Action Text\n\nThe `clipActionText: String?` is the text call to action if the clip associated with the event has a primary action link.\n\n### Clip Action URL\n\nThe `clipActionUrl: String?` is the URL linked to from the primary action if a clip associated with the event has a primary action.\n\n### Clip Action Type\n\nThe `clipActionType: String?` is the type of the primary action on a clip associated with the event. If there is no action button then the value is nil.\n\n### Collection\n\nThe `collection` is the ID of the collection if a story or clip is being played from a collection.\n\n### Collection Title\n\nThe `collectionTitle: String?` is the title of the collection if clip is being played from a collection.\n\n### Container Title\n\nThe `containerTitle` is the title of the collection if a story or clip is being played from a collection.\n\n### Category Details\n\nThe `categoryDetails` is a list of Category Detail objects. The details are the name, ID, type and placement of the category.\n\n### Category Name\n\nThe `categoryName` of the category being navigated to or dismissed.\n\n### Category ID\n\nThe `categoryId` of the category being navigated to or dismissed.\n\n### Current Category\n\nThe `currentCategory` is the category for the row that is currently being interacted with. The information provided from this is the category title, ID and placement.\n\nThis is only included on story and ad events.\n\n### Captions Enabled\n\nThe `captionsEnabled` property indicates whether captions are currently enabled for the Clips Player. This is included in all Clip Analytics Events and represents the state of captions at the time the event occurred.\n\n### Start Position\n\nThe `startPosition: Int?` represents the playback position, in milliseconds, when the user started scrubbing the clip. This is only included for `ScrubbedClip` events.\n\n### End Position\n\nThe `endPosition: Int?` represents the playback position, in milliseconds, when the user stopped scrubbing the clip. This is only included for `ScrubbedClip` events.\n\n### Eyebrow\n\nThe `eyebrow: String?` is a text field displayed on stories and clips, typically shown above the main title as a subtitle or descriptor.\n\n### Scrub Direction\n\nThe `scrubDirection: String?` indicates whether the user scrubbed to a position forward or backward on a Clip. Possible values are `forward` and `backward`. This is only included for `ScrubbedClip` events.\n\n### Completion Type\n\nThe `completionType: String?` indicates how a user finished watching a Clip. Possible values are `natural` and `scrubbed`.\nThis is included for `FinishedClip` and `ClipCompletedLoop` events.\n\n### Sheet ID\n\nThe ID of the Sheet for which the event occurred.\n\n### Sheet Size\n\nThe height of the Sheet for which the event occurred. Possible values are `50`, `75`, and `100` (representing % of screen height).\n\n### Sheet Title\n\nThe title of the Sheet for which the event occurred.\n\n### Search From\n\nThe `searchFrom` indicates whether the Search for which the event is recorded was opened from Clips or Stories.\n\n### Is Suggestion\n\nThe `isSuggestion` indicates whether the Search for which the event is recorded used a suggested Search.\n\n> Note: When filters are opened (event), the Is Suggestion value should reflect what was used for the initial search performed before opening filters.\n\n### Initial Input\n\nThe `initialInput` this property tracks the input at the moment the suggestion was used.\n\n### Search Filter\n\nThe `searchFilter` property includes the content type and date posted used by search filter.\n\n### Search Sort\n\nThe `searchSort` field indicates method by which the relevant Story / Clip's search results were sorted.\n\n### Search Term\n\nThe `searchTerm` by which the Clips / Stories were searched, either entered in the search bar by the user or selected / filled from search suggestions.\n\n### Action Text\n\nThe `actionText: String?` property is used for general action text and can apply to both page actions and clip actions depending on the placement context.\n\n### Action Type\n\nThe `actionType: String?` property is used for general action types, and can apply to both page actions and clip actions depending on the placement context.\n\n### Action URL\n\nThe `actionUrl: String?` is the URL for the action link. This property is used for general action URLs in events and can apply to both page actions and clip actions depending on the placement context.\n\n### Action Class\n\nThe `actionClass: String?` identifies whether the action button that was tapped is a primary or secondary action. Possible values are `primary` and `secondary`. This is only included for `ClipActionButtonTapped` events.\n\n### Action Index\n\nThe `actionIndex: Int?` is the 1-based index of the secondary action that was tapped. This is only included for `ClipActionButtonTapped` events when a secondary action is tapped.\n\n### Tapped Clip Action Text\n\nThe `tappedClipActionText: String?` is the text of the specific action button (primary or secondary) that was tapped. This is only included for `ClipActionButtonTapped` events.\n\n### Tapped Clip Action URL\n\nThe `tappedClipActionUrl: String?` is the URL of the specific action button (primary or secondary) that was tapped. This is only included for `ClipActionButtonTapped` events.\n\n### Tapped Clip Action Type\n\nThe `tappedClipActionType: String?` is the type of the specific action button (primary or secondary) that was tapped. This is only included for `ClipActionButtonTapped` events.\n\n### Has Secondary Actions\n\nThe `clipHasSecondaryActions: Bool?` indicates whether the clip has any secondary actions. This is included in all Clip Analytics Events.\n\n### Secondary Actions Text\n\nThe `clipSecondaryActionsText: [String]?` is an array of all the text CTAs on secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.\n\n### Secondary Action URLs\n\nThe `clipSecondaryActionUrls: [String]?` is an array of all the URLs on secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.\n\n### Secondary Action Types\n\nThe `clipSecondaryActionTypes: [String]?` is an array of all the types of secondary actions for the clip. This is included in all Clip Analytics Events when the clip has secondary actions.\n\n### Card ID\n\nThe `cardId: String?` is the ID of the Card for which the event occurred. This is included for `CardTapped` event.\n\n### Card Action Type\n\nThe `cardActionType: String?` is the type of the action on the Card. This is included for `CardTapped` event.\n\n### Card Action URL\n\nThe `cardActionUrl: String?` is the URL for the link if the Card has an action. This is included for `CardTapped` event.\n\n### Card Aspect Ratio\n\nThe `cardAspectRatio: String?` is the aspect ratio of the Card. This is included for `CardTapped` event.\n\n### Card Background Type\n\nThe `cardBackgroundType: String?` is the type of background on the Card. This can have the value `image` or `video`. This is included for `CardTapped` event.\n\n### Card Collection ID\n\nThe `cardCollectionId: String?` is the ID of the collection the Card belongs to. This is included for `CardTapped` event.\n\n### Card Index\n\nThe `cardIndex: Int?` is the index of the Card in the collection.\n\n> Note: This value is 1-based.\n\n### Card Subtitle\n\nThe `cardSubtitle: String?` is the subtitle text displayed on the Card. This is included for `CardTapped` event.\n\n### Card Title\n\nThe `cardTitle: String?` is the title text displayed on the Card. This is included for `CardTapped` event.\n\n### Has Button\n\nThe `hasButton: Bool?` indicates whether the Card displayed a button. This is included for `CardViewed` and `CardTapped` events.\n\n### Has Action\n\nThe SDK does not emit a `hasAction` property. Use `pageHasAction` (story/page-based ad events) or `clipHasAction` (clip-based ad events) depending on the ad placement context.\n\n### Followable Category Limit Dialogue\n\nThe `followableCategoryLimitDialogue: String?` is the text displayed in the Followable Category Limit dialogue box. This is included for `FollowableCategoryLimitShown`, `FollowableCategoryLimitActionButtonTapped`, and `FollowableCategoryLimitDismissed` events.\n\n### Followable Category Limit Action Text\n\nThe `followableCategoryLimitActionText: String?` is the text displayed on the customisable action button in the Followable Category Limit dialogue box. This is included for `FollowableCategoryLimitShown`, `FollowableCategoryLimitActionButtonTapped`, and `FollowableCategoryLimitDismissed` events.\n\n### Followable Category Limit Action URL\n\nThe `followableCategoryLimitActionUrl: String?` is the URL associated with the customisable action button in the Followable Category Limit dialogue box. This is included for `FollowableCategoryLimitShown`, `FollowableCategoryLimitActionButtonTapped`, and `FollowableCategoryLimitDismissed` events.\n\n### Is Muted\n\nThe `isMuted: Bool?` indicates whether the audio is currently muted when the event occurred. This property is included in all Story, Clip, Ad, and video Card analytics events when the mute state is known and represents the mute state at the time the event was tracked. Permanently muted video Cards and video Cards marked as having no audio report `true`; image and non-video Card events report `nil`.\n\n### Metadata\n\nThe `metadata: [String: String]?` contains custom metadata associated with the content for which the event occurred. For Clip events, this contains the metadata from the associated clip. For Story events, this contains the metadata from the associated page. This property is included in all Story and Clip analytics events.\n\n### Context\n\n`context: StorytellerAnalyticsContext?` contains host-defined attribution data. `StorytellerAnalyticsContext` is a type alias for `[String: String]`; the SDK does not prescribe the keys.\n\nYou can provide context through:\n\n- `StorytellerStoriesListConfiguration`\n- `StorytellerClipsListConfiguration`\n- `StorytellerClipCollectionConfiguration`\n- `StorytellerCardConfiguration`\n- `StorytellerHomeConfiguration`\n\nThe SDK carries that context into `StorytellerUserActivityData.context` for events it can attribute to the configured surface and content opened from it. Consume it in `StorytellerDelegate.onUserActivityOccurred`:\n\n<!-- storyteller-swift-example: id=analytics-context target=sdk-ios context=file -->\n\n```swift\nimport StorytellerSDK\n\nlet analyticsContext: StorytellerAnalyticsContext = [\n \"location\": \"home\",\n \"campaign\": \"summer-league\"\n]\n\nlet clipsConfiguration = StorytellerClipsListConfiguration(\n collectionId: \"top-plays\",\n context: analyticsContext\n)\n\nfinal class AnalyticsDelegate: StorytellerDelegate {\n func onUserActivityOccurred(\n type: StorytellerUserActivity.EventType,\n data: StorytellerUserActivityData\n ) {\n guard let location = data.context?[\"location\"] else { return }\n print(\"Storyteller event \\(type) came from \\(location)\")\n }\n}\n```\n\nThe callback is delivered only when `enableUserActivityTracking` is enabled. Ad events are additionally gated by `enableAdTracking`.\n\nThe Showcase app demonstrates an optional app-defined key namespace and consumption in [`StorytellerTrackingDelegate`](https://github.com/getstoryteller/storyteller-showcase-ios/blob/11.6.1/main/ShowcaseApp/Analytics/StorytellerTrackingDelegate.swift#L10).\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}