The SDK reports events and asks for ad settings through delegate objects. You set one global delegate on Storyteller.sharedInstance, and you can set a delegate on each view. Every callback is optional. For setup steps, see Handle delegates and callbacks.
Called before an ad request when your tenant uses a third-party ad server, such as Google Ad Manager. With Storyteller first-party ads, the SDK does not call it.
Google Ad Manager ad unit, in the form /[NETWORK_CODE]/[UNIT_CODE]. A configuration without slot is not valid
customTargeting
AdTargeting
No
Key-value pairs for the ad request. Values are strings or arrays of strings
publisherProvidedId
string or null
No
Publisher Provided ID (PPID). The SDK trims whitespace and omits an empty value
type
'doubleclick'
No
Ad server type
The SDK adds its default targeting keys and lets your customTargeting values override them. When enableAdTracking is false, the SDK omits its default keys and publisherProvidedId, and still sends your customTargeting.
AdConfig and AdTargeting are not exported by name. The declared AdConfig union also includes { type: 'custom'; remoteUrl: string }, which the SDK uses for Storyteller first-party ads. The SDK ignores that shape when your delegate returns it.
Since: 10.0.0 moved the callback to the global delegate. publisherProvidedId was added in 10.13.6
Called when a user taps an in-app action on a Story Page or a Clip. Implement it to route the URL inside your application. Without this callback, in-app actions open like regular URLs.
Called each time the view starts loading its content. This happens after the constructor, after a source change (categories, collection, clipId, or externalId), on reloadData, and when a Clips view refreshes after its player closes.
Called when the Story or Clip player that the view opened is dismissed. A tap on the Clips player top-level back button calls onTopLevelBackTapped instead.
Called when a user taps the top-level back button. The button shows only when topLevelBackButtonEnabled is true. Without this callback, the SDK calls window.history.back().
{"slug": "reference-callbacks", "page_title": "Callbacks", "page_url": "reference/callbacks/", "canonical_url": "/web/reference/callbacks/", "markdown": "# Callbacks\n\nThe SDK reports events and asks for ad settings through delegate objects. You set one global delegate on `Storyteller.sharedInstance`, and you can set a delegate on each view. Every callback is optional. For setup steps, see [Handle delegates and callbacks](../delegates/index.md).\n\n## Delegate interfaces\n\nThe SDK defines three delegate interfaces:\n\n| Interface | Set it on | Callbacks |\n| --- | --- | --- |\n| [`IStorytellerDelegate`](#istorytellerdelegate) | [`Storyteller.sharedInstance.delegate`](storyteller.md#delegate) | `onUserActivityOccurred`, `onShareButtonTapped`, `getAdConfig`, `userNavigatedToApp` |\n| [`IListViewDelegate`](#ilistviewdelegate) | The `delegate` of a Stories or Clips row or grid | `onDataLoadStarted`, `onDataLoadComplete`, `onPlayerDismissed` |\n| [`IStorytellerClipsPlayerDelegate`](#istorytellerclipsplayerdelegate) | The `delegate` of a `StorytellerClipsPlayerView` or `StorytellerEmbeddedClipsPlayerView` | The `IListViewDelegate` callbacks, plus `onTopLevelBackTapped` |\n\nAssigning a delegate object replaces the previous one, so include every callback that you need in each assignment.\n\n## `IStorytellerDelegate`\n\n```typescript\ninterface IStorytellerDelegate {\n onUserActivityOccurred?: (\n type: ActivityType,\n data: UserActivityData\n ) => void;\n onShareButtonTapped?: (\n text: string,\n title: string,\n url: string\n ) => Promise<void>;\n getAdConfig?: (\n adRequestInfo: StorytellerAdRequestInfo\n ) => AdConfig | null;\n userNavigatedToApp?: (url: string) => void;\n}\n```\n\nThe global delegate handles events from every Story and Clip player on the page.\n\n```typescript\nStoryteller.sharedInstance.delegate = {\n onUserActivityOccurred: (type, data) => {\n console.log(type, data.context);\n },\n};\n```\n\n- **Guide**: [Handle global callbacks](../StorytellerDelegate.md#methods)\n\n### `onUserActivityOccurred`\n\n```typescript\nonUserActivityOccurred?: (type: ActivityType, data: UserActivityData) => void\n```\n\nCalled for each analytics event. The SDK ignores the return value.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `type` | [`ActivityType`](types.md#activitytype) | The event name, such as `openedStory` |\n| `data` | [`UserActivityData`](types.md#useractivitydata) | The event properties. Each event page lists the properties that it sets |\n\nThe [privacy options](storyteller.md#eventtrackingoptions) control the callback:\n\n- The callback runs only when `enableUserActivityTracking` is `true`\n- Ad events reach the callback only when `enableAdTracking` is `true`\n- When `enableFullVideoAnalytics` is `false`, the SDK sets `storyId`, `storyTitle`, `storyDisplayTitle`, `pageId`, `pageTitle`, `clipId`, and `clipTitle` to `null`\n\n`data.context` holds the view's [`configuration.context`](../Analytics.md#context), unless that value is `undefined`. Assign the delegate before `initialize` to receive the [`sdkInitialized` event](../Analytics.md#sdk-initialization).\n\n- **Since**: 10.0.0 moved the callback to the global delegate\n- **Guides**: [Integrate analytics](../Analytics.md#event-types), [Story events](../analytics/StoryEvents.md), [Clip events](../analytics/ClipEvents.md), [Ad events](../analytics/AdEvents.md)\n\n### `onShareButtonTapped`\n\n```typescript\nonShareButtonTapped?: (\n text: string,\n title: string,\n url: string\n) => Promise<void>\n```\n\nCalled when a user taps the link share button in the Story player or the Clips player. Implement it to replace the browser share sheet.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `text` | `string` | Share text. For a Clip, the Clip description |\n| `title` | `string` | Share title. For a Story, the Story title. For a Clip, the Clip description |\n| `url` | `string` | The link to share |\n\nThe returned promise controls what happens next:\n\n- **Resolves**: the SDK records the `shareSuccess` event and resumes playback\n- **Rejects**: the SDK resumes playback without a `shareSuccess` event\n- **Missing or throws**: the SDK calls `navigator.share` instead\n\nThe player pauses while the share runs.\n\n- **Since**: 10.0.0. Since 10.4.6, the SDK falls back to `navigator.share`\n- **Guide**: [Handle global callbacks](../StorytellerDelegate.md#methods)\n\n### `getAdConfig`\n\n```typescript\ngetAdConfig?: (adRequestInfo: StorytellerAdRequestInfo) => AdConfig | null\n```\n\nCalled before an ad request when your tenant uses a third-party ad server, such as Google Ad Manager. With Storyteller first-party ads, the SDK does not call it.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `adRequestInfo` | [`StorytellerAdRequestInfo`](types.md#storytelleradrequestinfo) | The Story or Clip context of the ad slot |\n\nReturn an ad configuration, or `null` to send no ad request. The SDK uses this shape of the declared `AdConfig` union:\n\n```typescript\ninterface IntegratingAppAdConfig {\n type?: 'doubleclick';\n slot: string;\n customTargeting?: AdTargeting;\n publisherProvidedId?: string | null;\n}\n\ninterface AdTargeting {\n [index: string]: string | string[];\n}\n```\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `slot` | `string` | Yes | Google Ad Manager ad unit, in the form `/[NETWORK_CODE]/[UNIT_CODE]`. A configuration without `slot` is not valid |\n| `customTargeting` | `AdTargeting` | No | Key-value pairs for the ad request. Values are strings or arrays of strings |\n| `publisherProvidedId` | `string` or `null` | No | Publisher Provided ID (PPID). The SDK trims whitespace and omits an empty value |\n| `type` | `'doubleclick'` | No | Ad server type |\n\nThe SDK adds its default targeting keys and lets your `customTargeting` values override them. When `enableAdTracking` is `false`, the SDK omits its default keys and `publisherProvidedId`, and still sends your `customTargeting`.\n\n`AdConfig` and `AdTargeting` are not exported by name. The declared `AdConfig` union also includes `{ type: 'custom'; remoteUrl: string }`, which the SDK uses for Storyteller first-party ads. The SDK ignores that shape when your delegate returns it.\n\n- **Since**: 10.0.0 moved the callback to the global delegate. `publisherProvidedId` was added in 10.13.6\n- **Guides**: [Google Ad Manager integration](../Ads.md#storyteller-ad-manager-integration), [Default Targeting](../Ads.md#default-targeting), [AdRequestInfo](../Ads.md#adrequestinfo)\n\n### `userNavigatedToApp`\n\n```typescript\nuserNavigatedToApp?: (url: string) => void\n```\n\nCalled when a user taps an in-app action on a Story Page or a Clip. Implement it to route the URL inside your application. Without this callback, in-app actions open like regular URLs.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `url` | `string` | The action URL set in the Storyteller CMS |\n\n- **Since**: 10.6.0\n- **Guide**: [Handle global callbacks](../StorytellerDelegate.md#methods)\n\n## `IListViewDelegate`\n\n```typescript\ninterface IListViewDelegate {\n onDataLoadStarted?: () => void;\n onDataLoadComplete?: (\n success: boolean,\n error: Error | null,\n dataCount: number\n ) => void;\n onPlayerDismissed?: () => void;\n}\n```\n\nA view delegate handles events from one view. The SDK fills callbacks that you leave out with no-op functions.\n\n```typescript\nconst storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\n\nstoryRow.delegate = {\n onDataLoadStarted: () => console.log('Loading Stories'),\n onDataLoadComplete: (success, error, dataCount) => {\n console.log(success, error, dataCount);\n },\n};\n```\n\n- **Since**: 10.0.0 renamed these callbacks\n- **Guide**: [Handle view callbacks](../StorytellerListViewDelegate.md#delegate-methods)\n\n### `onDataLoadStarted`\n\n```typescript\nonDataLoadStarted?: () => void\n```\n\nCalled each time the view starts loading its content. This happens after the constructor, after a source change (`categories`, `collection`, `clipId`, or `externalId`), on [`reloadData`](views.md#reloaddata), and when a Clips view refreshes after its player closes.\n\n### `onDataLoadComplete`\n\n```typescript\nonDataLoadComplete?: (\n success: boolean,\n error: Error | null,\n dataCount: number\n) => void\n```\n\nCalled when the content request finishes.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `success` | `boolean` | `true` when the request succeeded |\n| `error` | `Error` or `null` | `null` on success. On failure, the request error. When the failure is not an `Error`, the SDK passes an `Error` with the message `Network Error` |\n| `dataCount` | `number` | Stories views: the number of Stories loaded. Clips views: the number of Clips in the first page. Single-Clip players: `1`. `0` on failure |\n\nLater Clips pages load as users reach the end of the content, and they do not call this callback. See [Clips paging](../StorytellerListView.md#clips-paging).\n\n### `onPlayerDismissed`\n\n```typescript\nonPlayerDismissed?: () => void\n```\n\nCalled when the Story or Clip player that the view opened is dismissed. A tap on the Clips player top-level back button calls [`onTopLevelBackTapped`](#ontoplevelbacktapped) instead.\n\n## `IStorytellerClipsPlayerDelegate`\n\n```typescript\ninterface IStorytellerClipsPlayerDelegate extends IListViewDelegate {\n onTopLevelBackTapped?: () => void;\n}\n```\n\nThe delegate of `StorytellerClipsPlayerView` and `StorytellerEmbeddedClipsPlayerView`. It supports the [`IListViewDelegate`](#ilistviewdelegate) callbacks.\n\n### `onTopLevelBackTapped`\n\n```typescript\nonTopLevelBackTapped?: () => void\n```\n\nCalled when a user taps the top-level back button. The button shows only when [`topLevelBackButtonEnabled`](views.md#toplevelbackbuttonenabled) is `true`. Without this callback, the SDK calls `window.history.back()`.\n\n```typescript\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n onTopLevelBackTapped: () => {\n window.history.back();\n },\n};\n```\n\n- **Since**: 10.13.6\n- **Guide**: [Handle view callbacks](../StorytellerListViewDelegate.md#delegate-methods)\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}