{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Storyteller Web SDK","text":"<p>Use the Storyteller Web SDK to show Stories and Clips on your website. These guides are for web developers: install the SDK, show your first Story row, then add the views and integrations you need.</p> <p> Show your first Story row Next step: initialize the SDK and show a row of Stories on your page. </p> Stories <p>Show Story tiles in a row or grid. Selecting a tile opens the Story player.</p> Add a Story row Add a Story grid Clips <p>Show Clip tiles in a row or grid, or play Clips in a player on your page.</p> Add a Clips row Add a Clips player to a page"},{"location":"#st-install","title":"Install the SDK","text":"Install with a script tag Load a fixed SDK version from the Storyteller CDN. No build step. Install from npm Import the package and its stylesheet in a bundled app. Use React or Next.js Initialize the SDK in the browser and destroy views on unmount. <p>Before you install, check what you need. Code examples link to the private Storyteller Web Showcase: get access to the Showcase source.</p>"},{"location":"#st-content","title":"Choose what to show","text":"Choose a view"},{"location":"#st-keep-building","title":"More guides","text":"Appearance and contentThemes, views, users, and privacy <ul> <li>Customize themesStyle tiles, players, Polls, and Quizzes.</li> <li>Configure viewsSet Categories, collections, and display limits.</li> <li>Identify and personalize usersSet user IDs, user attributes, and the Clips locale.</li> <li>Control privacy and trackingApply your users' consent choices.</li> </ul> Analytics, callbacks, and adsEvents, delegates, and ad setup <ul> <li>Integrate analyticsSend Story, Clip, Poll, Quiz, and ad events to your analytics tool.</li> <li>Handle delegates and callbacksRespond to loading, sharing, and player events.</li> <li>Integrate adsShow Storyteller or Google Ad Manager ads.</li> </ul> Help and referenceTroubleshooting, upgrades, and API details <ul> <li>Troubleshoot an integrationFind the first step that failed.</li> <li>Migrate from version 10 to 11Update and test a 10.13 integration.</li> <li>Open a player programmaticallyOpen Stories and Clips from your own buttons and links.</li> <li>Use additional SDK methodsCount content, turn on logging, and read SDK state.</li> <li>API referenceLook up every public class, method, and type.</li> <li>Use docs with AIGive your coding assistant the SDK docs.</li> <li>Release notesSee what changed in each version.</li> </ul>"},{"location":"AI/","title":"Use the docs with AI assistants","text":"<p>The Storyteller Web SDK docs are also published as plain-text files for AI coding assistants, such as GitHub Copilot, Claude, Codex, ChatGPT, and Cursor. Give your assistant these files so that its answers use the Web SDK API as documented.</p>"},{"location":"AI/#why-use-ai-assistants-with-documentation","title":"Why use the docs with an AI assistant","text":"<p>An assistant that has the Storyteller docs in context can:</p> <ul> <li>Suggest code that matches the Web SDK API</li> <li>Help you troubleshoot initialization, themes, analytics, and ads</li> <li>Use the documented options and defaults instead of guessing them</li> </ul> <p>Check important answers against the docs pages.</p>"},{"location":"AI/#copy-one-page","title":"Copy one page","text":"<p>Every page except the documentation home has a Copy for AI button next to its title. The button copies the page's AI file: a summary of the page, followed by the full page in Markdown. Paste it into your assistant's chat. On this page, the button copies the whole bundle described in the next section.</p> <p>The button's menu also has Copy as Markdown, which copies only the page's Markdown.</p>"},{"location":"AI/#adding-documentation-to-your-editor","title":"Add the whole bundle to your project","text":"<p>Download the documentation bundle from <code>https://docs.getstoryteller.com/web/ai/llms.txt</code>. It contains a summary of every page in navigation order. Each summary starts with a <code>&lt;PAGE: slug&gt;</code> marker.</p> <p>To use the bundle in your project:</p> <ol> <li>Create a <code>.ai/</code> directory in your project.</li> <li>Save the bundle as <code>.ai/storyteller-web-sdk-docs.md</code>.</li> <li>Point your assistant to that file and mention it in your prompts.</li> </ol> <p>In an editor assistant, such as Cursor, Zed, or GitHub Copilot, attach or reference the saved file in the chat. In a web-based assistant, upload the file, or paste its contents at the start of a new chat. Long pastes may be truncated.</p>"},{"location":"AI/#when-to-use-per-page-files","title":"Use per-page files","text":"<p>When you need one topic, give your assistant that page's file. It contains the page summary and the full page. Each page's file is at:</p> <pre><code>https://docs.getstoryteller.com/web/ai/llms-&lt;slug&gt;.txt\n</code></pre> <p>The <code>&lt;slug&gt;</code> is the same slug as in the bundle's <code>&lt;PAGE: slug&gt;</code> marker. To work it out from a page's URL, take the path after <code>https://docs.getstoryteller.com/web/</code> and remove the trailing slash. Replace each <code>/</code> with <code>-</code>, add a hyphen before each capital letter inside a word, and use lowercase letters. For a section overview page whose URL ends in a folder name, add <code>-index</code>.</p> Page URL path Slug File <code>Themes/</code> <code>themes</code> <code>llms-themes.txt</code> <code>StorytellerRowView/</code> <code>storyteller-row-view</code> <code>llms-storyteller-row-view.txt</code> <code>getting-started/npm/</code> <code>getting-started-npm</code> <code>llms-getting-started-npm.txt</code> <code>getting-started/</code> <code>getting-started-index</code> <code>llms-getting-started-index.txt</code>"},{"location":"AI/#release-notes","title":"Release notes","text":"<p>The bundle doesn't include the release notes. Download them separately from <code>https://docs.getstoryteller.com/web/ai/llms-changelog.txt</code>, or copy them from the Release notes page.</p>"},{"location":"AI/#search-index","title":"Search the docs","text":"<p>An assistant that can fetch URLs can use the docs search index to find the right page: <code>https://docs.getstoryteller.com/web/search/search_index.json</code>. It lists the title, location, and text of each page and section. Check important answers against the pages it finds.</p>"},{"location":"AI/#example-prompts","title":"Example prompts","text":"<ul> <li>\"Using the Storyteller Web SDK docs, initialize Storyteller and show a Story   row on my page.\"</li> <li>\"Show a minimal <code>StorytellerStoriesRowView</code> integration and how to reload its   data.\"</li> <li>\"Which callbacks do I implement to send Storyteller analytics events to my   analytics tool?\"</li> <li>\"Help me build a <code>UiTheme</code> with our brand colors for light and dark mode.\"</li> <li>\"Implement <code>getAdConfig</code> for Google Ad Manager with Story and Clip Category   targeting.\"</li> <li>\"Help me fix this Storyteller initialization error: [paste the error].\"</li> </ul>"},{"location":"AdditionalMethods/","title":"Use additional SDK methods","text":"<p>This page lists the properties and methods of <code>Storyteller.sharedInstance</code>, the SDK object you initialize and use to open players, count content, and read SDK state. For methods on a view, such as <code>reloadData</code> and <code>destroy</code>, see Configure views. The API reference lists every public member, including <code>theme</code>, <code>currentTheme</code>, <code>currentApiKey</code>, and <code>customInstanceHost</code>.</p> <p>Examples that use <code>await</code> must run inside an <code>async</code> function or a JavaScript module.</p>"},{"location":"AdditionalMethods/#setting-the-global-storytellerdelegate","title":"Set the global delegate","text":"<pre><code>Storyteller.sharedInstance.delegate = {\n  // Your callbacks here\n};\n</code></pre> <p>Learn more</p> <p>To set the global delegate, see Handle global callbacks.</p> <p></p>"},{"location":"AdditionalMethods/#instance-properties","title":"Instance properties","text":""},{"location":"AdditionalMethods/#isinitialized","title":"isInitialized","text":"<pre><code>readonly isInitialized: boolean\n</code></pre> <p><code>true</code> after an <code>initialize</code> call succeeds.</p> <pre><code>const initialized = Storyteller.sharedInstance.isInitialized;\n</code></pre>"},{"location":"AdditionalMethods/#isplayervisible","title":"isPlayerVisible","text":"<pre><code>readonly isPlayerVisible: boolean\n</code></pre> <p><code>true</code> while a Story or Clips player is open, and <code>false</code> after it is dismissed.</p> <pre><code>const isStoryPlayerVisible = Storyteller.sharedInstance.isPlayerVisible;\n</code></pre>"},{"location":"AdditionalMethods/#version","title":"version","text":"<pre><code>version: string\n</code></pre> <p>The SDK version.</p> <pre><code>const storytellerVersion = Storyteller.sharedInstance.version;\n</code></pre>"},{"location":"AdditionalMethods/#eventtrackingoptions","title":"<code>eventTrackingOptions</code>","text":"<p>The privacy and tracking options. Each assignment replaces every option: options you leave out return to their defaults. See Control privacy and tracking.</p> <p></p>"},{"location":"AdditionalMethods/#instance-methods","title":"Instance methods","text":""},{"location":"AdditionalMethods/#initialize","title":"initialize","text":"<pre><code>initialize(apiKey: string, userInput?: { externalId?: string | null }): Promise&lt;void&gt;\n</code></pre> <p>Initializes the SDK with your API key and, optionally, your ID for the current user. Call it before you use other methods, and wait for the promise.</p> <ul> <li><code>apiKey</code>: your Storyteller API key</li> <li><code>userInput.externalId</code>: your ID for the signed-in user, or <code>null</code> for an anonymous user. See Setting a user ID.</li> </ul> <pre><code>try {\n  await Storyteller.sharedInstance.initialize('demo-api-key', {\n    externalId: 'your-user-id',\n  });\n} catch (error) {\n  console.error('Storyteller could not initialize.', error);\n}\n</code></pre> <ul> <li>Calls with the same API key and <code>externalId</code> made while an earlier call is still running share that call's promise. React Strict Mode's repeated effects therefore initialize the SDK once.</li> <li>With the default privacy options, <code>initialize</code> also loads the user's viewing history from Storyteller, and rejects if that request fails.</li> <li>Each call resets <code>Storyteller.sharedInstance.theme</code> to its defaults. Set the global theme after the promise resolves.</li> <li>The promise rejects with an <code>Error</code> whose message starts with the error type, such as <code>InvalidApiKeyError</code>, <code>NetworkError</code>, or <code>NetworkTimeoutError</code>. A call with no API key rejects with a string. See Handle initialization errors.</li> </ul>"},{"location":"AdditionalMethods/#dismissplayer","title":"dismissPlayer","text":"<pre><code>dismissPlayer(animated: boolean): void\n</code></pre> <p>Closes the open Story or Clips player. If no player is open, it does nothing. It doesn't close a <code>StorytellerEmbeddedClipsPlayerView</code>.</p> <ul> <li><code>animated</code>: <code>true</code> plays the close animation.</li> </ul> <pre><code>Storyteller.sharedInstance.dismissPlayer(true);\n</code></pre>"},{"location":"AdditionalMethods/#disableplayback","title":"disablePlayback","text":"<pre><code>disablePlayback(): void\n</code></pre> <p>Pauses the open Story player and the current Clip in every Clips player on the page. Stories and Clips that open while playback is disabled stay paused until you call <code>enablePlayback</code>. Use it when your page shows something over Storyteller content, such as your own video or a dialog.</p> <pre><code>Storyteller.sharedInstance.disablePlayback();\n</code></pre>"},{"location":"AdditionalMethods/#enableplayback","title":"enablePlayback","text":"<pre><code>enablePlayback(): void\n</code></pre> <p>Allows playback again after <code>disablePlayback</code>, and resumes the open Story and the current Clip. Playback is enabled by default.</p> <pre><code>Storyteller.sharedInstance.enablePlayback();\n</code></pre>"},{"location":"AdditionalMethods/#enablelogging","title":"enableLogging","text":"<pre><code>enableLogging(): void\n</code></pre> <p>Turns on the SDK's info, warning, and log messages in the browser console. The SDK always logs errors. Use it for debugging and monitoring, and call it before <code>initialize</code> to see initialization logs.</p> <pre><code>Storyteller.sharedInstance.enableLogging();\n</code></pre> <p>The Storyteller Web Showcase turns on logging in its debug mode with this <code>enableLogging</code> call.</p>"},{"location":"AdditionalMethods/#getstoriescount","title":"getStoriesCount","text":"<pre><code>getStoriesCount(categoryIds: string[]): Promise&lt;number&gt;\n</code></pre> <p>Returns the total number of available Stories in the given Category IDs. The SDK sends one small count request for each Category and adds the results. An empty array returns <code>0</code> without a request.</p> <p>The SDK sends the count requests only after <code>initialize</code> succeeds. A count call made before or during initialization waits for it. If initialization never starts or fails, the promise stays pending until a later <code>initialize</code> call succeeds. A failed count request rejects the promise.</p> <p>Use the count method for an optional row that should appear only when it has content. Load a primary row directly, without a count, to avoid an extra request.</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key');\n\nconst count = await Storyteller.sharedInstance.getStoriesCount(['category-id']);\n\nif (count &gt; 0) {\n  // Show the row only when the Category has Stories\n  new Storyteller.StorytellerStoriesRowView('stories-row-id', ['category-id']);\n}\n</code></pre>"},{"location":"AdditionalMethods/#getclipscount","title":"getClipsCount","text":"<pre><code>getClipsCount(collectionId: string): Promise&lt;number&gt;\n</code></pre> <p>Returns the number of available Clips in the collection. It waits for initialization and handles errors in the same way as <code>getStoriesCount</code>. Use it before you create an optional Clips view.</p> <pre><code>const clipsCount = await Storyteller.sharedInstance.getClipsCount('collection-id');\n</code></pre>"},{"location":"AdditionalMethods/#openstory","title":"openStory","text":"<pre><code>openStory(id: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story with this ID. The promise rejects if the SDK can't open the Story, for example because it can't be found. See Open a player programmatically.</p> <pre><code>await Storyteller.sharedInstance.openStory('story-id');\n</code></pre>"},{"location":"AdditionalMethods/#openstorybyexternalid","title":"openStoryByExternalId","text":"<pre><code>openStoryByExternalId(externalId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story with this external ID. The promise rejects if the SDK can't open the Story, for example because it can't be found.</p> <pre><code>await Storyteller.sharedInstance.openStoryByExternalId('story-external-id');\n</code></pre>"},{"location":"AdditionalMethods/#openpage","title":"openPage","text":"<pre><code>openPage(pageId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story that contains this Page, starting at the Page. The promise rejects if the SDK can't open the Page, for example because it can't be found.</p> <pre><code>await Storyteller.sharedInstance.openPage('page-id');\n</code></pre>"},{"location":"AdditionalMethods/#opencategory","title":"openCategory","text":"<pre><code>openCategory(categoryId: string, storyId?: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story player for the Category, at the Story with the ID <code>storyId</code>. If you leave out <code>storyId</code>, or it isn't in the Category, the first Story in the Category opens. The promise rejects if the SDK can't open the Category, for example because it can't be found.</p> <pre><code>await Storyteller.sharedInstance.openCategory('category-id', 'story-id');\n</code></pre>"},{"location":"AdditionalMethods/#opencollection","title":"openCollection","text":"<pre><code>openCollection(\n  collectionId: string,\n  destination?: { categoryId?: string; clipId?: string },\n  openedReason?: OpenedReason.deepLink\n): Promise&lt;void&gt;\n</code></pre> <p>Opens the Clips player for the collection. It accepts the following parameters:</p> <ul> <li><code>collectionId</code>: the ID of the collection to open.</li> <li><code>destination</code>: the <code>clipId</code> or <code>categoryId</code> to show when the collection opens. If you leave it out, or the Clip or Category isn't in the collection, the first Clip in the collection opens.</li> <li><code>openedReason</code>: the reason reported in analytics events. It accepts only <code>Storyteller.OpenedReason.deepLink</code>: pass it when the user arrived through a deep link. If you leave it out, the SDK sets the reason.</li> </ul> <p>The promise rejects if the SDK can't open the collection, for example because it can't be found.</p> <pre><code>await Storyteller.sharedInstance.openCollection(\n  'collection-id',\n  { clipId: 'clip-id' },\n  Storyteller.OpenedReason.deepLink\n);\n</code></pre>"},{"location":"AdditionalMethods/#openclipbyexternalid","title":"openClipByExternalId","text":"<pre><code>openClipByExternalId(collectionId: string, externalId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Clips player for the collection, at the Clip with this external ID. The promise rejects if the SDK can't open the Clip, for example because the collection has no Clip with that external ID.</p> <pre><code>await Storyteller.sharedInstance.openClipByExternalId(\n  'collection-id',\n  'clip-external-id'\n);\n</code></pre>"},{"location":"AdditionalMethods/#deprecated-members","title":"Deprecated members","text":"<p>These members still work in version 11, but don't use them in new code:</p> Member Use instead <code>openClip(id, onError?)</code> <code>openCollection</code> or <code>openClipByExternalId</code> <code>enableEventTracking()</code> <code>eventTrackingOptions</code> <code>disableEventTracking()</code> <code>eventTrackingOptions</code> <code>currentUserId</code> None. It always returns an empty string."},{"location":"Ads/","title":"Integrate ads","text":"<p>Storyteller can show ads in Stories and Clips from two sources:</p> <ul> <li>First Party Ads, which you create in the Storyteller CMS. They need no   code.</li> <li>Google Ad Manager (GAM) ads. Implement the <code>getAdConfig</code> callback to tell   the SDK which ad unit to request and which targeting to send.</li> </ul>"},{"location":"Ads/#ad-sources","title":"Ad Sources","text":"<p>Storyteller sets which ad source your tenant uses. To change it, contact the Storyteller Delivery Team.</p>"},{"location":"Ads/#storyteller-first-party-ads","title":"Storyteller First Party Ads","text":"<p>If your tenant uses Storyteller First Party Ads, you manage them in the Storyteller CMS and don't change your integration code. The SDK loads and shows these ads itself.</p>"},{"location":"Ads/#storyteller-ad-manager-integration","title":"Google Ad Manager integration","text":"<p>The SDK requests these ads from Google Ad Manager. For other ad servers, contact the Storyteller Delivery Team.</p> <p>Implement the <code>getAdConfig</code> callback on the global delegate (<code>IStorytellerDelegate</code>, see StorytellerDelegate). The SDK calls it each time it needs an ad, and only when your tenant uses Google Ad Manager ads.</p> <p>Assigning <code>Storyteller.sharedInstance.delegate</code> replaces every global callback. The samples below spread the current delegate to keep your other callbacks.</p> JavaScriptTypeScript <pre><code>Storyteller.sharedInstance.delegate = {\n  ...Storyteller.sharedInstance.delegate,\n  getAdConfig: (adRequestInfo) =&gt; {\n    // Only Story ad requests have `story`. Clips ad requests have `clip`.\n    const customTargeting = adRequestInfo.story\n      ? {\n          storytellerStoryCategories: adRequestInfo.story.categories.map(({ name }) =&gt; name),\n        }\n      : {\n          storytellerClipCategories: adRequestInfo.clip.categories.map(({ name }) =&gt; name),\n          storytellerNextClipCategories:\n            adRequestInfo.nextClip?.categories.map(({ name }) =&gt; name) || [],\n        };\n\n    return {\n      slot: '/30497361/your_ad_unit',\n      publisherProvidedId: 'your-publisher-provided-id',\n      customTargeting,\n    };\n  },\n};\n</code></pre> <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport type {\n  StorytellerAdRequestInfo,\n  StorytellerStoriesAdRequestInfo,\n} from '@getstoryteller/storyteller-sdk-javascript';\n\nfunction isStoryAd(\n  adRequestInfo: StorytellerAdRequestInfo\n): adRequestInfo is StorytellerStoriesAdRequestInfo {\n  return 'story' in adRequestInfo;\n}\n\nStoryteller.sharedInstance.delegate = {\n  ...Storyteller.sharedInstance.delegate,\n  getAdConfig: (adRequestInfo) =&gt; {\n    const customTargeting: Record&lt;string, string[]&gt; = isStoryAd(adRequestInfo)\n      ? {\n          storytellerStoryCategories: adRequestInfo.story.categories.map(({ name }) =&gt; name),\n        }\n      : {\n          storytellerClipCategories: adRequestInfo.clip.categories.map(({ name }) =&gt; name),\n          storytellerNextClipCategories:\n            adRequestInfo.nextClip?.categories.map(({ name }) =&gt; name) || [],\n        };\n\n    return {\n      slot: '/30497361/your_ad_unit',\n      publisherProvidedId: 'your-publisher-provided-id',\n      customTargeting,\n    };\n  },\n};\n</code></pre> <p>The Storyteller Web Showcase builds the <code>getAdConfig</code> result in <code>buildAdConfig</code> with the ad slot and custom targeting values.</p>"},{"location":"Ads/#return-value","title":"Return value","text":"<p><code>getAdConfig</code> returns an object with the fields below, or <code>null</code> to request no ad. An object without <code>slot</code> also requests no ad. Return the object directly: the SDK doesn't wait for a promise. For the full type, see <code>getAdConfig</code> in the callback reference.</p> Field Description <code>slot</code> Required. The ID of your GAM ad unit, in the form <code>/[NETWORK_CODE]/[UNIT_CODE]</code>. The ad unit must serve 1x1 ads. For details, see Google's guides to custom ad creative and programmatic ad creative. <code>publisherProvidedId</code> Optional Publisher Provided ID (PPID) for Google Ad Manager. This value is sent as GAM's PPID field, not as a custom targeting KVP. The SDK trims whitespace, omits empty values, and omits this value when ad tracking is disabled. <code>customTargeting</code> Optional key-value pairs (KVPs) that the SDK sends to GAM for ad targeting. The SDK adds the default targeting values, and a key you return replaces the default key with the same name. The SDK doesn't copy KVPs that the rest of your page sets. <p>Values such as <code>ddid</code>, <code>isLoggedIn</code>, <code>gdpr</code>, <code>us_privacy</code>, <code>gpp</code>, <code>gpp_sid</code>, and other app-owned ad/privacy KVPs should be supplied through <code>customTargeting</code>. PPID should be supplied through <code>publisherProvidedId</code>.</p> <p><code>customTargeting</code> values can be strings or arrays of strings. Use arrays for multi-value GAM KVPs so each value is passed as a distinct targeting value.</p> <p>When ad tracking is off (<code>enableAdTracking: false</code>), the SDK omits the default targeting and <code>publisherProvidedId</code>. It still sends the <code>customTargeting</code> you return.</p>"},{"location":"Ads/#default-targeting","title":"Default Targeting","text":"<p>By default, the Storyteller SDK sets the following <code>customTargeting</code> values:</p>"},{"location":"Ads/#stories-default-targeting","title":"Stories","text":"Property Name Property Type Description Example value <code>stCurrentCategory</code> <code>string</code> The external ID of the current Story Category. \"top-stories\" <code>stPlacement</code> <code>string</code> The placement <code>code</code> of the current Story Category. <code>web-top-stories</code> <code>stCategories</code> <code>string[]</code> External IDs of the current Story Categories. <code>[\"top-stories\", \"web-stories\"]</code>"},{"location":"Ads/#clips-default-targeting","title":"Clips","text":"Property Name Property Type Description Example value <code>stCollection</code> <code>string</code> The ID of the current Clip Collection. <code>live-clips</code> <code>stClipCategories</code> <code>string[]</code> External IDs of the current Clip Categories. <code>[\"top-clips\", \"web-clips\"]</code> <code>stNextClipCategories</code> <code>string[]</code> External IDs of the next Clip Categories. <code>[\"top-clips\", \"web-clips\"]</code>"},{"location":"Ads/#adrequestinfo","title":"AdRequestInfo","text":"<p>The <code>StorytellerAdRequestInfo</code> object passed to this callback can be one of two types, depending on whether the user is viewing Stories or Clips:</p> <pre><code>export type StorytellerStoriesAdRequestInfo = {\n  placement: string;\n  categories: string[];\n  story: {\n    categories: CategoryDetail[];\n  };\n};\n\nexport type StorytellerClipsAdRequestInfo = {\n  collection: string;\n  clip: {\n    categories: ClipCategory[];\n  };\n  nextClip?: {\n    categories: ClipCategory[];\n  };\n};\n</code></pre> <p>This object contains details about the Story or Clip the user is viewing. Pass them to your ad server to target the ad. Only Story ad requests have <code>story</code>, so check for it before you read it, as the samples above do.</p>"},{"location":"Ads/#stories-adrequestinfo","title":"Stories","text":"<p>Story ad requests contain:</p> Property Description <code>placement: string</code> A string which uniquely identifies the placement in which the Story is being shown <code>categories: string[]</code> A list of Category String IDs which have been assigned to the Stories list. Note that every Category in this list will appear on every Story in the list. This list can be useful to know in which context the user is currently viewing Stories. <code>story: ItemInfo</code> Metadata about the Story after which the requested Ad will be placed <p>The <code>ItemInfo</code> object has the following properties:</p> Property Description <code>categories: CategoryDetail[]</code> An array of Categories which have been assigned to the Story <p>The <code>CategoryDetail</code> object has the following properties:</p> Property Description <code>name: string</code> A human readable name for the Category <code>externalId: string</code> The external ID of the Category, set in the Storyteller CMS"},{"location":"Ads/#clips-adrequestinfo","title":"Clips","text":"<p>Clips ad requests contain:</p> Property Description <code>collection: string</code> A string which uniquely identifies the Collection that the Clips are assigned to <code>clip: ItemInfo</code> Metadata about the Clip after which the requested Ad will be placed <code>nextClip: ItemInfo</code> Optional. Metadata about the Clip that follows the Ad, when there is one <p>The <code>ItemInfo</code> object has the following properties:</p> Property Description <code>categories: ClipCategory[]</code> An array of Categories which have been assigned to the Clip. <p>The <code>ClipCategory</code> object has the following properties:</p> Property Description <code>name: string</code> A human readable name for the Category <code>externalId: string</code> The string ID for the Category"},{"location":"Analytics/","title":"Integrate analytics","text":"<p>The SDK reports what users do in Stories, Clips, Polls, Quizzes, and ads through the <code>onUserActivityOccurred</code> callback. This page shows how to receive these events and forward them to your analytics tool, what the startup event contains, and how to add placement context. The event pages list every event and its fields.</p>"},{"location":"Analytics/#receive-events","title":"Receive events","text":"<p>Add an <code>onUserActivityOccurred</code> callback to <code>Storyteller.sharedInstance.delegate</code> before you call <code>initialize</code>, so you also receive the startup event. The callback receives the event type and an object with the event's fields.</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    analytics.track(type, data);\n  },\n};\n\nawait Storyteller.sharedInstance.initialize('demo-api-key');\n</code></pre> <p>Replace <code>analytics.track</code> with the call your analytics tool uses. To handle one event type, compare <code>type</code> with a <code>Storyteller.ActivityType</code> value, for example <code>Storyteller.ActivityType.openedStory</code>. In TypeScript, the delegate type is <code>IStorytellerDelegate</code>.</p> <p>Assigning <code>Storyteller.sharedInstance.delegate</code> replaces all four global callbacks: <code>onUserActivityOccurred</code>, <code>onShareButtonTapped</code>, <code>getAdConfig</code>, and <code>userNavigatedToApp</code>. Define all your callbacks in one object, or spread the current delegate:</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  ...Storyteller.sharedInstance.delegate,\n  onUserActivityOccurred: (type, data) =&gt; {\n    analytics.track(type, data);\n  },\n};\n</code></pre> <p>The SDK calls <code>onUserActivityOccurred</code> only when <code>enableUserActivityTracking</code> is <code>true</code>, which is the default. Ad events also need <code>enableAdTracking</code>. When <code>enableFullVideoAnalytics</code> is <code>false</code>, content IDs and titles are <code>null</code>. See Control privacy and tracking for these options.</p> <p>The Storyteller Web Showcase handles these events in <code>onUserActivityOccurred</code>. Handle global callbacks describes the other callbacks on the delegate.</p>"},{"location":"Analytics/#event-types","title":"Event types","text":"<p>The SDK sends these kinds of events:</p> <ul> <li>SDK initialization</li> <li>Story Events</li> <li>Poll Events</li> <li>Quiz Events</li> <li>Clip Events</li> <li>Ad Events</li> </ul> <p>Each event page lists:</p> <ul> <li>the events of that kind</li> <li>when each event is recorded</li> <li>the fields sent with each event</li> </ul>"},{"location":"Analytics/#sdk-initialization","title":"SDK initialization","text":"<p>The SDK sends <code>sdkInitialized</code> (<code>Storyteller.ActivityType.sdkInitialized</code>) when an <code>initialize</code> call gets the result of the settings request for your tenant:</p> <ul> <li><code>initializationSucceeded</code> is <code>true</code> when the settings load. Later   <code>initialize</code> calls after a successful one don't send the event again.</li> <li><code>initializationSucceeded</code> is <code>false</code> when the settings request fails. The   <code>initialize</code> promise then rejects.</li> </ul> <p><code>initialize</code> rejects without sending <code>sdkInitialized</code> when the API key is missing, when the SDK can't save the user ID, or when the request for the user's viewing history fails. With the default privacy options, the SDK waits for the viewing history before the settings, so an invalid API key or a network outage usually fails that request first. Handle startup failures in the <code>catch</code> block of <code>initialize</code>, not with this event.</p> <p>Set the delegate before you call <code>initialize</code> to receive this event.</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    if (type === Storyteller.ActivityType.sdkInitialized) {\n      console.log(data.initializationSucceeded);\n    }\n  },\n};\n</code></pre> <p>The event contains the following properties:</p> Property Value <code>initializationSucceeded</code> <code>true</code> or <code>false</code>. <code>enableAdTracking</code>, <code>enableFullVideoAnalytics</code>, <code>enablePersonalization</code>, <code>enableRemoteViewingStore</code>, <code>enableStorytellerTracking</code>, <code>enableUserActivityTracking</code> The tracking options in effect. <code>enablePersonalization</code> and <code>enableStorytellerTracking</code> are <code>false</code> when <code>enableFunctionalCookies</code> is <code>false</code>. The event doesn't include <code>enableFunctionalCookies</code> or <code>disabledFunctionalFeatures</code>. <code>appId</code> The page origin and path, for example <code>https://www.example.com/news</code>, without the query string or hash. <code>null</code> during server rendering. <code>deviceType</code> <code>Phone</code>, <code>Tablet</code>, <code>TV</code>, or <code>Desktop</code>. <code>deviceBrand</code>, <code>deviceModel</code> Detected from the browser's user agent. <code>'none'</code> when unknown. <code>operatingSystem</code>, <code>osVersion</code> Detected from the browser's user agent. <code>'none'</code> when unknown. <code>screenResolution</code> The browser viewport size as <code>&lt;width&gt;x&lt;height&gt;</code> in CSS pixels. <code>null</code> during server rendering. <p>The callback runs when <code>enableUserActivityTracking</code> is enabled. Storyteller server delivery also follows <code>enableFunctionalCookies</code> and <code>enableStorytellerTracking</code>. See Control privacy and tracking for these settings.</p> <p></p>"},{"location":"Analytics/#context","title":"Add placement context to events","text":"<p>Use <code>context</code> to record where on your site an event came from, such as the page and module. <code>context?: unknown</code> contains host-defined attribution data. The SDK does not prescribe its shape. It returns the configured value in <code>UserActivityData.context</code> for events that it can attribute to the view and to content opened from that view.</p> <p>You can provide context through the configuration for:</p> <ul> <li><code>StorytellerStoriesRowView</code></li> <li><code>StorytellerStoriesGridView</code></li> <li><code>StorytellerClipsRowView</code></li> <li><code>StorytellerClipsGridView</code></li> <li><code>StorytellerClipsPlayerView</code></li> <li><code>StorytellerEmbeddedClipsPlayerView</code></li> </ul> <pre><code>const storiesRow = new Storyteller.StorytellerStoriesRowView('stories-row');\nconst analyticsContext = {\n  location: 'home',\n  module: 'top-stories',\n  sortOrder: 10,\n};\n\nstoriesRow.configuration = {\n  context: analyticsContext,\n};\n\nStoryteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    console.log(type, data.context);\n  },\n};\n</code></pre> <p>You can replace the value while the view is mounted. Reassign the <code>configuration</code> object with the new value:</p> <pre><code>storiesRow.configuration = {\n  context: {\n    location: 'sports',\n    module: 'latest-stories',\n  },\n};\n</code></pre> <p>The callback is delivered only when <code>enableUserActivityTracking</code> is enabled. It omits <code>context</code> when the configured value is <code>undefined</code>. Explicit values such as <code>null</code>, <code>false</code>, <code>0</code>, and an empty string remain in the callback.</p> <p>If a Story or Clip opens related content from an SDK action, the related player events keep the source placement context. This applies to child Stories, Story categories, Clips, and Clip collections. A direct hash URL or deep link has no source placement, so the SDK uses the destination view's configured context or omits the field.</p> <p>The SDK returns context only to the delegate in the same browser client. It does not add context to Storyteller analytics API requests. Your application owns the value, its storage, and its transfer to any analytics provider. Keep credentials and personal data out of this field.</p>"},{"location":"Analytics/#event-data","title":"Event data","text":""},{"location":"Analytics/#openedreason","title":"OpenedReason","text":"<p>The action which the user took to open the Story:</p> Value Description <code>storyListTap</code> The user tapped the Story in the list <code>deepLink</code> The user navigated directly to a Story URL <code>swipe</code> The user swiped left or right to change the Story <code>automaticPlayback</code> The previous Page finished, and the player moved on to the next one <code>tap</code> The user tapped to navigate <p>or Clip:</p> Value Description <code>clipListTap</code> The user tapped the Clip in the list <code>categoryListTap</code> The user tapped a Clip Category label <code>categoryBackTap</code> The user tapped the back button in a Clip Category <code>deepLink</code> The user navigated directly to a Clip URL <code>swipe</code> The user swiped to the next or previous Clip"},{"location":"Analytics/#dismissedreason","title":"DismissedReason","text":"<p>The reason the Story or Clip was dismissed:</p> Value Description <code>backgroundTapped</code> The user tapped the background to dismiss the Story (on desktop) <code>closeButtonTapped</code> The user tapped close to dismiss the Story <code>swipedDown</code> The user swiped down to dismiss the Story <code>swipedFinalStory</code> The user swiped the final Story to dismiss it <code>swipedFirstStory</code> The user swiped the first Story to dismiss it <code>skippedFinalPage</code> The user tapped to skip the final Page of the final Story <code>backTapped</code> The user tapped the browser back button to dismiss the Story view <code>backButtonTapped</code> The user tapped the back button to dismiss the Clips player <code>completedFinalPage</code> The user completed the final Page of the final Story <code>instanceMethod</code> The player was dismissed programmatically using the <code>dismissPlayer</code> method <code>escapeKeyPressed</code> The user pressed the <code>Esc</code> key to dismiss the Story <code>windowUnload</code> The user navigated away by closing the page or entering a new URL in the browser bar"},{"location":"Changelog/","title":"Changelog","text":"<p>Links in these release notes go to the current guides, which describe the latest version.</p>"},{"location":"Changelog/#1101-20260930","title":"11.0.1 - 2026.09.30","text":""},{"location":"Changelog/#bug-fixes","title":"Bug Fixes","text":"<ul> <li>A Story opened from a row sends   <code>openedStory</code> as it   opens. Since 10.13.13, the event could arrive only when the player closed,   or not at all. The first <code>openedPage</code> after a row tap reports <code>storyListTap</code>   again.</li> </ul>"},{"location":"Changelog/#1100-20260925","title":"11.0.0 - 2026.09.25","text":"<p>Version 11.0.0 changes where the SDK keeps viewing history, how the script build loads its code, and how the npm package declares its files and dependencies. Read Migrate from version 10 to 11 before you update.</p>"},{"location":"Changelog/#breaking-changes","title":"Breaking Changes","text":"<ul> <li>Viewing history now comes from Storyteller. With the default privacy   options, <code>initialize</code> loads the user's read Pages, Clip likes and views, and   Poll and Quiz answers, and waits for them. History for an <code>externalId</code>   follows the user across browsers and devices. Read state that 10.13   recorded carries over with the default privacy options. See   Remote viewing store.</li> <li><code>initialize</code> rejects with <code>InvalidApiKeyError</code>, <code>NetworkError</code>, or   <code>NetworkTimeoutError</code> when the viewing-history request fails. No   <code>sdkInitialized</code> event is sent in that case. See   Handle initialization errors.</li> <li>The SDK calls a new viewing-history endpoint, and Clips requests use a new   path and send a new request header. If a proxy or allowlist sits in front of   the Storyteller API, allow them. See the   migration guide.</li> <li>Renamed the local storage keys for viewing history. <code>Storyteller.likes</code>,   <code>Storyteller.viewedClips</code>, <code>Storyteller.pollAnswers</code>,   <code>Storyteller.triviaQuizAnswers</code>, and <code>Storyteller.readPages</code> replace   <code>Storyteller.clipLikes</code>, <code>Storyteller.clipsViewed</code>,   <code>Storyteller.pollAnswerMap</code>, <code>Storyteller.quizAnswerMap</code>, and   <code>Storyteller.storiesReadMap</code>. The SDK does not read or remove the earlier   keys. With <code>enableRemoteViewingStore: false</code>, history saved by 10.13 does   not carry over. See   local storage items.</li> <li>The script build loads Story player, Clips player, Poll, Quiz, and caption   code as separate files from the directory that served <code>storyteller.min.js</code>.   If you host the SDK files yourself, deploy every file in the version's <code>dist</code>   directory and keep the file names. Your Content Security Policy must allow   scripts from that directory. See   Host the SDK files.</li> <li>The npm package declares <code>@types/react</code> (<code>&gt;=17 &lt;20</code>) and   <code>@types/react-router-dom</code> (<code>^5.1.7</code>) as peer dependencies, because its   TypeScript declarations import them. npm 7 and later installs them. See   TypeScript declarations.</li> <li>The npm package adds <code>import</code> and <code>require</code> entry points and publishes its   declarations at <code>dist/index.npm.d.ts</code>. It no longer ships <code>index.js</code>,   <code>types/*.d.ts</code>, or SDK source files. Import only the package root and   <code>dist/storyteller.min.css</code>.</li> <li>The SDK no longer installs the <code>reflect-metadata</code> polyfill on the page's   global <code>Reflect</code> object. If your code uses <code>Reflect.getMetadata</code>, import   <code>reflect-metadata</code> in your application.</li> <li><code>ActivityType</code> has a new <code>sdkInitialized</code>   member. Update exhaustive <code>switch</code> statements over <code>ActivityType</code>.</li> <li><code>Story</code> has new <code>pinnedChipText</code> and <code>customLiveChipText</code> properties for   custom chip text. Update typed   test data.</li> <li>Removed the undocumented <code>QuizRenderer.clearQuizData()</code> method.</li> </ul>"},{"location":"Changelog/#new-features","title":"New Features","text":"<ul> <li>Added <code>destroy()</code> to every view. Call it   before your application removes or replaces the view's container.</li> <li>Added the <code>sdkInitialized</code> activity event.   <code>onUserActivityOccurred</code> receives it when   <code>enableUserActivityTracking</code> is on. <code>initializationSucceeded</code> is <code>true</code> when   Settings load and <code>false</code> when the Settings request fails. Other startup   failures reject <code>initialize</code> without this event.</li> <li>When the Stories API uses started-aware ordering,   rows and grids show Stories the user has not opened, then Stories in   progress, then finished Stories. Pinned and Live Stories keep their   priority.</li> <li>Clips rows, grids, and players that show a Collection   load more Clips as the user reaches   the last loaded Clip, including inside a Category. <code>onDataLoadComplete</code>   reports only the first page.</li> <li>Story tiles show custom Live and pinned chip text   from Story content.</li> <li>The <code>liveChip</code> theme for round and rectangular tiles adds   <code>unreadBackgroundGradient</code>, <code>readBorderColor</code>, and <code>unreadBorderColor</code>. See   Story tile chips.</li> <li>The Clips player shows a Clip's long description   when it has one. Users can expand the title, description, and Categories,   and scroll them when they are long.</li> <li>The remote Clips player theme can turn on   compact Clip action buttons. If your   remote theme already sets <code>clipsActionButtonCompactSize</code>, the buttons change   when you update.</li> <li>The remote Clips player theme can hide like and share counts with   <code>showLikeCount</code> and <code>showShareCount</code>. If your remote   theme already sets them, the counts change when you update.</li> <li>Every Story, Poll, Quiz, and Story ad activity event now includes   <code>categoryDetails</code>. Clip events already included it, and Clip ad events have   no Category fields. See the Story,   Poll, Quiz, and   Ad events.</li> </ul>"},{"location":"Changelog/#performance","title":"Performance","text":"<ul> <li>The script-tag (CDN) build downloads less code up front. The main script is   about 77 KB gzip, down from about 197 KB in 10.13.17. The script that runs   inside each Story is about 34 KB, down from about 191 KB.</li> <li>The script build downloads Story player, Clips player, Poll, Quiz, and   caption code the first time a page needs it. A Stories view also starts a   low-priority download of the AMP player script before the first Story opens.   See version 11 behavior.</li> <li>The npm package still includes all SDK code in one JavaScript file. Your   bundler decides what your users download and when.</li> <li><code>initialize</code> calls with the same API key and <code>externalId</code>, made while an   earlier call is still running, share its startup work.</li> <li>Story and Clips views avoid repeated layout and lookup work.</li> <li>The SDK is compiled to ES2020. Supported browsers are unchanged from 10.13.</li> </ul>"},{"location":"Changelog/#improvements","title":"Improvements","text":"<ul> <li>Updated the default AMP runtime, which renders Stories, to <code>20260925.1</code>. The   Story ad, Story swipe, and next Story button fixes below come from this   update.</li> <li>Poll and Quiz answers can show two lines.   Longer answers are clipped.</li> <li>Each wrapped line of a Clip or Story caption   has its own background. Captions align to the start of the line, including   on right-to-left pages.</li> <li>Clip captions appear after the Clip starts playing.</li> <li>The Story CC control appears only on video Pages, and it moves above a   call-to-action that overlaps it.</li> <li>A caption theme field set for a feed now overrides only that field of the   tenant caption theme. Before, a feed caption   theme replaced the tenant theme as a whole.</li> <li>Caption defaults changed to 16 px text, the font's natural line height, and   a <code>#171A25</code> background. In 10.13 they were 18 px text, a 22 px line height,   and a <code>#000000</code> background.</li> <li>Stories that have no Pages are no longer shown.</li> </ul>"},{"location":"Changelog/#bug-fixes_1","title":"Bug Fixes","text":"<ul> <li>If a user pauses a Story and then answers its Poll or Quiz, the Story   resumes and the pause button updates.</li> <li>When <code>playAllStories</code> is off, the Story player moves   from read pinned or Live Stories to the next unread Story instead of   closing.</li> <li>When the player refreshes an open Story, the Story keeps its pinned or Live   position.</li> <li>On desktop, the next Story button is no longer disabled on the last pinned   or Live Story when the player continues to another Story.</li> <li>Forward navigation stays available when a user returns to a Story they   finished earlier in the same player session.</li> <li>Browser Back and Forward move between the Pages of an open Story.</li> <li>Going back to an earlier Story shows the Story ad from that point again.</li> <li>Going back through a Page Ad returns to the Page before the ad.</li> <li>An ad after the last Page of the last pinned Story no longer loops. The   next tap or swipe moves on or closes the player.</li> <li>Swiping between Stories no longer gets stuck where read Stories meet unread   Stories.</li> <li>Clips ad frequency and the first ad position reset when a user closes and   reopens the Clips player.</li> <li>Clips ads keep appearing after a user changes swipe direction.</li> <li>Users can swipe, drag, or scroll from a Clips image ad to the next or   previous Clip.</li> <li>On desktop, a loaded Clips ad in the preview no longer turns into a Clip,   and an ad that has not loaded is skipped before the preview shows it.</li> <li>In Safari, the Clips player background no longer flashes black between   Clips.</li> <li>In Safari, a paused Clip shows its image instead of a black frame.</li> <li>On macOS, switching to another window no longer briefly plays the Clip.</li> <li>In a short looping Clips feed, the Clip on screen plays. Keyboard and screen   reader users reach only that Clip's controls.</li> <li>Escape closes only the visible Story player. In Safari, closing Stories   repeatedly no longer raises a <code>history.replaceState</code> error.</li> <li>Activity requests sent while the SDK saves the user ID now include   <code>externalId</code>.</li> <li>A Quiz completion is recorded when the score is zero.</li> <li>Repeated taps record a Poll or Quiz answer once.</li> <li><code>StorytellerEmbeddedClipsPlayerView</code>   no longer locks page scrolling when it first renders.</li> </ul>"},{"location":"Changelog/#documentation","title":"Documentation","text":"<ul> <li>Reorganized the docs by task. New guides show how to install the SDK   with a script tag or   from npm,   use React or Next.js,   choose a view,   show Polls and Quizzes,   troubleshoot an integration, and   migrate from version 10 to 11.</li> <li>Added an API reference for every public method,   property, type, and callback, and a guide to   open a player programmatically.</li> <li>Added a guide to use these docs with AI assistants.</li> </ul>"},{"location":"Changelog/#101318-20260930","title":"10.13.18 - 2026.09.30","text":""},{"location":"Changelog/#bug-fixes_2","title":"Bug Fixes","text":"<ul> <li>A Story opened from a row sends   <code>openedStory</code> as it   opens. Since 10.13.13, the event could arrive only when the player closed,   or not at all. The first <code>openedPage</code> after a row tap reports <code>storyListTap</code>   again.</li> </ul>"},{"location":"Changelog/#101317-20260923","title":"10.13.17 - 2026.09.23","text":""},{"location":"Changelog/#new-features_1","title":"New Features","text":"<ul> <li>Added <code>configuration.context</code> to the <code>onUserActivityOccurred</code> callback data.   The selected view supplies the context when views share a player and when an   SDK action opens related content. Context changes apply while a view remains   mounted. The value stays outside Storyteller activity API requests.</li> </ul>"},{"location":"Changelog/#101316-20260915","title":"10.13.16 - 2026.09.15","text":""},{"location":"Changelog/#new-features_2","title":"New Features","text":"<ul> <li>Added <code>getStoriesCount</code> and <code>getClipsCount</code> methods to the shared SDK   instance. Integrations can check for content before they create an optional   list view.</li> </ul>"},{"location":"Changelog/#improvements_1","title":"Improvements","text":"<ul> <li>Row images now receive their source when they approach the horizontal   viewport. Story players keep every AMP Story entry and create a poster image   only for the active Story.</li> </ul>"},{"location":"Changelog/#101315-20260910","title":"10.13.15 - 2026.09.10","text":""},{"location":"Changelog/#bug-fixes_3","title":"Bug Fixes","text":"<ul> <li>Fixed Stories skipping their first page right after a swipe to the next Story. The background Story refresh introduced in 10.13.13 hot-swapped <code>playerStories</code>, which restarted the player and re-showed the active Story on its read-state initial page (the page after the one on screen). The same re-run also switched the swiped-to Story to single-Story playback mode, reset its view start time, and registered a duplicate read-state listener on every refresh. Story switches now leave the running player alone and a refreshed Story only re-shows when its active page no longer exists.</li> </ul>"},{"location":"Changelog/#101314-20260910","title":"10.13.14 - 2026.09.10","text":""},{"location":"Changelog/#bug-fixes_4","title":"Bug Fixes","text":"<ul> <li>Updated the default AMP runtime to <code>20260910.1</code>, which keeps Story video-ad audio controls available when the ad capability signal and media setup complete in either order.</li> </ul>"},{"location":"Changelog/#101313-20260824","title":"10.13.13 - 2026.08.24","text":""},{"location":"Changelog/#new-features_3","title":"New Features","text":"<ul> <li>Added closed captions for Clips and Stories when the matching captions feature flag is enabled. The SDK supports WebVTT cues, a saved caption preference, caption theme settings, toggle analytics, and safe caption controls for Story media pages.</li> </ul>"},{"location":"Changelog/#bug-fixes_5","title":"Bug Fixes","text":"<ul> <li>Included the internal declaration files required by the published TypeScript definitions.</li> </ul>"},{"location":"Changelog/#101312-20260819","title":"10.13.12 - 2026.08.19","text":""},{"location":"Changelog/#bug-fixes_6","title":"Bug Fixes","text":"<ul> <li>Contained rejected activity-tracking requests inside the SDK so blocked or failed best-effort activity delivery does not reach host applications as an unhandled Promise rejection. Story navigation and existing activity callbacks continue unchanged.</li> </ul>"},{"location":"Changelog/#101311-20260817","title":"10.13.11 - 2026.08.17","text":""},{"location":"Changelog/#bug-fixes_7","title":"Bug Fixes","text":"<ul> <li>Updated the default AMP runtime to <code>20260817.1</code>, fixing captions-state synchronization and quiz result-page enablement during AMP page initialization while preserving useful errors for invalid page references.</li> </ul>"},{"location":"Changelog/#101310-20260807","title":"10.13.10 - 2026.08.07","text":""},{"location":"Changelog/#new-features_4","title":"New Features","text":"<ul> <li>Added <code>instructions.iconHighlightColor</code> and <code>instructions.iconColor</code> theme properties for independently styling the highlight and foreground colours of built-in Story instruction icons. <code>iconHighlightColor</code> falls back to <code>colors.primary</code>, while <code>iconColor</code> falls back to the effective <code>instructions.headingColor</code>. Existing custom <code>instructions.icons</code> URL overrides remain unchanged, so colour-only branding does not require custom icon assets.</li> </ul>"},{"location":"Changelog/#10139-20260729","title":"10.13.9 - 2026.07.29","text":""},{"location":"Changelog/#bug-fixes_8","title":"Bug Fixes","text":"<ul> <li>Fixed Story Page API host resolution so URL- and storage-provided <code>customInstanceHost</code> values cannot control iframe requests. Story Pages now use trusted server metadata when present and otherwise retain the existing environment-based API defaults.</li> </ul>"},{"location":"Changelog/#10138-20260709","title":"10.13.8 - 2026.07.09","text":""},{"location":"Changelog/#new-features_5","title":"New Features","text":"<ul> <li>Added <code>clipPlayer.showFeedTitle</code>, <code>clipPlayer.showClipTitle</code>, and <code>clipPlayer.showNavigationCategories</code> theme properties so Clips player integrations can hide feed-title, clip-title, and navigation-category chrome independently.</li> </ul>"},{"location":"Changelog/#10137-20260626","title":"10.13.7 - 2026.06.26","text":""},{"location":"Changelog/#new-features_6","title":"New Features","text":"<ul> <li>Added <code>StorytellerEmbeddedClipsPlayerView</code> as a first-class iframe-free embedded Clips player API with the same collection, <code>clipId</code>, and <code>externalId</code> source contract as <code>StorytellerClipsPlayerView</code>. See the embedded Clips player docs for initialization, sizing, configuration, and list configuration.</li> <li>Added RTL support across Stories rows, Clips rows, and the Story player, including right-to-left rail controls, edge fades, story text direction, and player controls. See RTL support.</li> </ul>"},{"location":"Changelog/#improvements_2","title":"Improvements","text":"<ul> <li>Updated the default AMP runtime to <code>20260626.1</code>.</li> </ul>"},{"location":"Changelog/#10136-20260602","title":"10.13.6 - 2026.06.02","text":""},{"location":"Changelog/#new-features_7","title":"New Features","text":"<ul> <li>Added true single-clip playback support for <code>StorytellerClipsPlayerView</code>, allowing embedded Clips players to initialize from either <code>clipId</code> or <code>externalId</code> while preserving the existing collection-based constructor.</li> <li>Added <code>topLevelBackButtonEnabled</code> and <code>onTopLevelBackTapped</code> support for embedded <code>StorytellerClipsPlayerView</code> instances so host apps can render and handle a top-level back button.</li> <li>Added <code>theme.player.icons.back</code> support for customizing the Clips player back/close icon.</li> <li>Added <code>publisherProvidedId</code> support to Google Ad Manager ad configuration so integrations can send PPID separately from custom targeting KVPs.</li> </ul>"},{"location":"Changelog/#bug-fixes_9","title":"Bug Fixes","text":"<ul> <li>Fixed <code>recordActivity</code> payloads so activity <code>externalId</code> is still included when personalization tracking is disabled.</li> </ul>"},{"location":"Changelog/#10135-20260518","title":"10.13.5 - 2026.05.18","text":""},{"location":"Changelog/#bug-fixes_10","title":"Bug Fixes","text":"<ul> <li>Fixed Clips video ad playback state so user-paused ads stay paused after CTA taps, mute changes, browser tab lifecycle changes, and ad completion events.</li> <li>Fixed iOS Safari GAM clip video ads so they start muted when needed for autoplay, resume cleanly after clip navigation, and keep poster surfaces visible instead of showing a black frame.</li> <li>Fixed GAM SafeFrame video ads so poster fallbacks remain visible until a video frame is painted, looped video ads initialize correctly, and paused ads are not resumed by mute changes.</li> <li>Reapplied the Web SDK GAM category targeting fix so SDK-provided category KVPs are passed as arrays, preventing double-encoded comma separators in AMP DoubleClick requests.</li> <li>Fixed production AMP URL resolution for the hotfix path and updated the default AMP runtime to <code>20260518.1</code>.</li> </ul>"},{"location":"Changelog/#10134-20260430","title":"10.13.4 - 2026.04.30","text":""},{"location":"Changelog/#bug-fixes_11","title":"Bug Fixes","text":"<ul> <li>Fixed the npm package artifact so package-root imports expose the expected SDK exports and the packaged CSS file is included.</li> </ul>"},{"location":"Changelog/#10133-20260429","title":"10.13.3 - 2026.04.29","text":""},{"location":"Changelog/#bug-fixes_12","title":"Bug Fixes","text":"<ul> <li>Fixed Web SDK GAM category targeting values so SDK-provided category KVPs are passed as arrays, preventing double-encoded comma separators in AMP DoubleClick requests.</li> <li>Updated the default AMP runtime to <code>20260428.1</code> to include story audio and story ad playback fixes.</li> <li>Fixed Story player start/close handling so visible players can reassert playback and unmute state during story navigation without resetting the active player.</li> </ul>"},{"location":"Changelog/#10132-2025121702","title":"10.13.2 - 2025.12.1702","text":""},{"location":"Changelog/#improvements_3","title":"Improvements","text":"<ul> <li>CSS formatting improvements</li> </ul>"},{"location":"Changelog/#10131-2025121701","title":"10.13.1 - 2025.12.1701","text":""},{"location":"Changelog/#improvements_4","title":"Improvements","text":"<ul> <li>The logic for updating the hash on Clip navigation now relies on the location pathname instead of the default history API behaviour (which uses <code>base</code> HTML elements if provided)</li> </ul>"},{"location":"Changelog/#10130-2025112601","title":"10.13.0 - 2025.11.2601","text":""},{"location":"Changelog/#new-features_8","title":"New Features","text":"<ul> <li>Add <code>stNextClipCategories</code> KVP to integrating app custom targeting</li> <li>Added <code>row.startPadding</code> and <code>row.endPadding</code> theme properties to add padding to a row that should be flush with the container on scroll</li> <li>Support for the \"Between Pages\" ad strategy</li> <li>Ad events now include an \"Ad Strategy\" field</li> <li>Added support for additional action types (linking to Stories, categories, Clips, and Collections)</li> <li>AAds between Stories now display even when a Story is skipped</li> </ul>"},{"location":"Changelog/#deprecations","title":"Deprecations","text":"<ul> <li>Deprecated <code>theme.storyTiles.title.show</code> property in favour of a value that can be set in the CMS. Starting from this version, this Theme property has no effect. Default value for the CMS property is <code>true</code>.</li> <li>Ad KVPs now match the mobile SDKs (<code>collection</code> was renamed to <code>stCollection</code>, <code>clipCategories</code> was renamed to <code>stClipCategories</code>, and so on)</li> </ul>"},{"location":"Changelog/#improvements_5","title":"Improvements","text":"<ul> <li>Added a retry button when a Clip or Story fails to load, replacing the infinite spinner</li> <li>If a row doesn't have a set height, it now defaults to a minimum height</li> <li>Improved focus outlines on row and grid items</li> <li>Removed pause button over image Clip ads</li> <li>Non-AMP ads in Clips no longer show pause/play controls since they cannot be paused</li> <li>Previous and Next Story buttons remain enabled when read/unread status is disabled for a row</li> </ul>"},{"location":"Changelog/#bug-fixes_13","title":"Bug Fixes","text":"<ul> <li>Fixed a bug where ad placement didn\u2019t consistently account for buffer logic</li> <li>Initial ad index now properly accounts for the previous Story\u2019s pages</li> </ul>"},{"location":"Changelog/#101210-2025112601","title":"10.12.10 - 2025.11.2601","text":""},{"location":"Changelog/#bug-fixes_14","title":"Bug Fixes","text":"<ul> <li>Fixed a bug with inconsistent loading of Stories after deleting pages or updating their targeting</li> </ul>"},{"location":"Changelog/#10129-2025111101","title":"10.12.9 - 2025.11.1101","text":""},{"location":"Changelog/#bug-fixes_15","title":"Bug Fixes","text":"<ul> <li>Fixed a bug with inconsistent loading of live Stories when some theme properties are not set</li> </ul>"},{"location":"Changelog/#10128-2025-1030","title":"10.12.8 - 2025-10.30","text":""},{"location":"Changelog/#bug-fixes_16","title":"Bug Fixes","text":"<ul> <li>Fixed a bug where it was possible for the wrong CTA to show under Stories ads after navigating back and forth</li> </ul>"},{"location":"Changelog/#10127-2025-10-24","title":"10.12.7 - 2025-10-24","text":""},{"location":"Changelog/#improvements_6","title":"Improvements","text":"<ul> <li>Added a <code>showScrollIndicator</code> theme property to hide/show scroll arrows in Stories/Clips rows</li> </ul>"},{"location":"Changelog/#10126-2025-10-23","title":"10.12.6 - 2025-10-23","text":""},{"location":"Changelog/#bug-fixes_17","title":"Bug Fixes","text":"<ul> <li>Fixed a bug where it was possible for the current category analytics property to be empty in Stories rows with multiple categories</li> </ul>"},{"location":"Changelog/#10125-2025-10-08","title":"10.12.5 - 2025-10-08","text":""},{"location":"Changelog/#bug-fixes_18","title":"Bug Fixes","text":"<ul> <li>Fixed a bug where it was possible for the \"actionButtonTapped\" event not to get triggered for actions that open in a new tab</li> </ul>"},{"location":"Changelog/#10125-alpha3-2025-09-24","title":"10.12.5 (alpha.3) - 2025-09-24","text":""},{"location":"Changelog/#improvements_7","title":"Improvements","text":"<ul> <li>Fixing generation of <code>.d.ts</code> files</li> </ul>"},{"location":"Changelog/#10125-alpha2-2025-09-23","title":"10.12.5 (alpha.2) - 2025-09-23","text":""},{"location":"Changelog/#improvements_8","title":"Improvements","text":"<ul> <li>Fixed a bug where tile size could grow for round tiles when <code>storyTiles.title.show</code> was set to <code>false</code></li> </ul>"},{"location":"Changelog/#10125-alpha1-2025-09-19","title":"10.12.5 (alpha.1) - 2025-09-19","text":""},{"location":"Changelog/#improvements_9","title":"Improvements","text":"<ul> <li>Further improvements to support for some CMPs</li> </ul>"},{"location":"Changelog/#10125-alpha0-2025-09-12","title":"10.12.5 (alpha.0) - 2025-09-12","text":""},{"location":"Changelog/#improvements_10","title":"Improvements","text":"<ul> <li>Improving support for some CMPs</li> </ul>"},{"location":"Changelog/#10124-2025-08-25","title":"10.12.4 - 2025-08-25","text":""},{"location":"Changelog/#bug-fixes_19","title":"Bug Fixes","text":"<ul> <li>Fixed an issue with the Clips player size on some Android devices</li> </ul>"},{"location":"Changelog/#10123-2025-08-22","title":"10.12.3 - 2025-08-22","text":""},{"location":"Changelog/#bug-fixes_20","title":"Bug Fixes","text":"<ul> <li>Improved the auto-advance behaviour of non-AMP ads in Firefox and Safari</li> </ul>"},{"location":"Changelog/#10122-2025-08-14","title":"10.12.2 - 2025-08-14","text":""},{"location":"Changelog/#new-features_9","title":"New Features","text":"<ul> <li>Introduced an initial index for the <code>betweenStoriesAndPages</code> and <code>betweenClips</code> ads strategies, that will be the index after which the first ad will appear. Can be configured in the CMS.</li> </ul>"},{"location":"Changelog/#10121-2025-07-22","title":"10.12.1 - 2025-07-22","text":""},{"location":"Changelog/#improvements_11","title":"Improvements","text":"<ul> <li>Added <code>clipShares</code> as a supported <code>disabledFunctionalFeatures</code> value in tracking preferences. For details, see the Privacy and Tracking documentation</li> </ul>"},{"location":"Changelog/#10120-2025-07-17","title":"10.12.0 - 2025-07-17","text":""},{"location":"Changelog/#improvements_12","title":"Improvements","text":"<ul> <li>Introduced <code>disabledFunctionalFeatures</code> option in tracking preferences. For details, see the Privacy and Tracking documentation</li> <li>Setting the user ID to <code>null</code> is now supported</li> <li>Introduced <code>enableRemoteViewingStore</code> option in tracking preferences. For details, see the Privacy and Tracking documentation</li> <li>The <code>recentStoryPlaybackMode</code> is now only saved to local storage if needed for analytics</li> <li>Stopped storing user attributes when the <code>enablePersonalization</code> tracking preference is set to <code>false</code></li> <li>Removed unused <code>settingsSavedDate</code> local storage item</li> </ul>"},{"location":"Changelog/#10111-2025-06-20","title":"10.11.1 - 2025-06-20","text":"<p>Improvements:</p> <ul> <li>Removed quiz share button from OneBox stories</li> </ul>"},{"location":"Changelog/#10110-2025-06-19","title":"10.11.0 - 2025-06-19","text":"<p>Breaking changes:</p> <ul> <li>Implemented VPPA compliance measures including SHA256 hashing for User IDs for requests and removal of Content ID from ad requests. See Privacy and Tracking for details.</li> <li>Deprecated <code>Storyteller.currentUserId</code> method as part of privacy enhancements.</li> <li>Added <code>enableFullVideoAnalytics</code> property to <code>eventTrackingOptions</code> for granular video analytics control. See Privacy and Tracking for details.</li> </ul> <p>Improvements:</p> <ul> <li>Improved VPPA compliance by removing direct user identifiers from various API requests. See Privacy and Tracking for details.</li> <li>Added support for <code>sheet</code> actions in Clips.</li> </ul>"},{"location":"Changelog/#1091-2025-06-02","title":"10.9.1 - 2025-06-02","text":"<p>Improvements:</p> <ul> <li>Moved some <code>dependencies</code> to <code>devDependencies</code></li> </ul>"},{"location":"Changelog/#1090-2025-04-02","title":"10.9.0 - 2025-04-02","text":"<p>Features:</p> <ul> <li>Added the <code>enableAdTracking</code> property to <code>eventTrackingOptions</code></li> </ul> <p>Improvements:</p> <ul> <li>Non-AMP ads are now supported in Clips as long as they are based on a Storyteller template</li> <li>Better tracking pixels support in Clip ads</li> </ul>"},{"location":"Changelog/#1080-2025-03-07","title":"10.8.0 - 2025-03-07","text":"<p>Improvements:</p> <ul> <li>The instructions screen is now only shown when opening a Story from the row (not when a Story is opened directly from its URL)</li> <li>The gradient behind the Story/Clip titles on rectangular tiles is now shown by default (it can be hidden by setting <code>storyTiles.rectangularTile.showGradient</code> to <code>false</code>)</li> <li>Better support for non-AMP ads</li> </ul>"},{"location":"Changelog/#1072-2025-01-23","title":"10.7.2 - 2025-01-23","text":"<p>Improvements:</p> <ul> <li>The instructions screen is now only shown once instead of once per Stories row/grid</li> </ul>"},{"location":"Changelog/#1071-2025-01-17","title":"10.7.1 - 2025-01-17","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a Safari iOS bug where it was possible for the borders of round thumbnails to disappear</li> <li>Fixed a bug where it was possible for some necessary events not to get reported to Storyteller</li> <li>Fixed a bug where it was possible for a Story row to not be clickable after opening a Story from its share link</li> </ul>"},{"location":"Changelog/#1070-2025-01-06","title":"10.7.0 - 2025-01-06","text":"<p>New Features:</p> <ul> <li>Added <code>#stories/[STORY_ID]</code>, <code>#clips/[COLLECTION_ID]</code>, and <code>#clips/[COLLECTION_ID]/[CLIP_ID]</code> routes</li> <li>Added support for reloading Stories and Clips views when exiting the player</li> <li>The <code>eventTrackingOptions</code> property can be used for customising the analytics and tracking behavior</li> </ul> <p>Improvements:</p> <ul> <li>The behaviour and signature of the <code>open*</code> methods now match the native SDKs:</li> </ul> <ul> <li><code>openStory</code> is now async</li> <li><code>openStoryByExternalId</code> is now supported</li> <li><code>openPage</code> is now async</li> <li><code>openCategory</code> is now async</li> <li><code>openClip</code> is now deprecated (please use <code>openCollection</code> instead)</li> <li><code>openCollection</code> is now async and accepts a destination argument with either a Clip ID or Category ID</li> <li><code>openClipByExternalId</code> is now supported</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug with linking to a Story not present on the page when <code>player.playAllStories</code> theme property was set to <code>false</code></li> <li>Fixed a bug where it was possible for the default basename of a view could be empty if no <code>data-base-url</code> was set</li> <li>Fixed a bug where it was possible for the Collection ID param of shared Clips to be empty</li> </ul>"},{"location":"Changelog/#1060-2024-12-17","title":"10.6.0 - 2024-12-17","text":"<p>New Features:</p> <ul> <li>Added <code>userNavigatedToApp</code> method to the Storyteller delegate</li> </ul> <p>Improvements:</p> <ul> <li>Added default custom targeting values to integrating app ad requests</li> </ul>"},{"location":"Changelog/#1053-2024-12-09","title":"10.5.3 - 2024-12-09","text":"<p>Improvements:</p> <ul> <li>Added accessible labels to button elements</li> </ul>"},{"location":"Changelog/#1052-2024-11-27","title":"10.5.2 - 2024-11-27","text":"<p>Improvements:</p> <ul> <li>Removed calls to deprecated Storyteller internal endpoint</li> </ul>"},{"location":"Changelog/#1051-2024-11-15","title":"10.5.1 - 2024-11-15","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for some Stories not to autoplay on iOS</li> </ul>"},{"location":"Changelog/#1050-2024-11-14","title":"10.5.0 - 2024-11-14","text":"<p>New Features:</p> <ul> <li>Added support for ads in the Clips Player</li> <li>Added support for \"Share media\" actions</li> <li>Added support for <code>enableViewedOrdering</code> in a Clips collection</li> </ul> <p>Improvements:</p> <ul> <li>Improved focus behaviour for the Story player navigation buttons</li> <li>Grid thumbnails now use the highest quality asset based on their size</li> <li>Added support for Storyteller ads with no actions</li> <li>Mobile CTAs are now aligned to the center by default</li> <li>Improved Story transitions and loading styles</li> <li>Improved full screen styles on mobile</li> <li>Added documentation for Clip events</li> <li>Improved error handling when initialising Storyteller rows in container with invalid IDs</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for iOS/Android specific actions to show in desktop browsers</li> <li>Fixed a bug where it was possible for some progress bars to experience a delay in loading</li> <li>Fixed a bug where it was possible for the <code>OpenedStory</code>, <code>SkippedStory</code>, <code>DismissedStory</code>, and <code>DismissedClips</code> events to not get recorded in some cases</li> <li>Fixed a bug where it was possible for a previously paused Story to be paused on reopen</li> <li>Fixed a bug where it was possible for an unread Story to be skipped by using the keyboard arrows</li> <li>Fixed a bug where it was possible for the audio of a previous Story to play over the current Story when using the keyboard to navigate</li> <li>Fixed a bug where it was possible for the like state of a clip to be inaccurate in some cases</li> <li>Fixed a bug where it was possible for the swipe up gesture to not open the CTA destination</li> </ul>"},{"location":"Changelog/#10411-2024-09-20","title":"10.4.11 - 2024-09-20","text":"<p>Improvements:</p> <ul> <li>User attributes now automatically get cleared when a new API key or user ID is provided</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the \"New\" chips to be visible on Stories with read/unread ordering disabled</li> </ul>"},{"location":"Changelog/#10410-2024-09-06","title":"10.4.10 - 2024-09-06","text":"<p>New Features:</p> <ul> <li>Added the <code>player.disableUrls</code> and <code>clipPlayer.disableUrls</code> theme properties</li> </ul> <p>Improvements:</p> <ul> <li>Updated the logic for generating unique ad requests correlators</li> </ul>"},{"location":"Changelog/#1049-2024-09-03","title":"10.4.9 - 2024-09-03","text":"<p>New Features:</p> <ul> <li>Added support for image titles in clip collections</li> </ul> <p>Improvements:</p> <ul> <li>Increased cases where the unmute state is persisted in Chromium browsers</li> </ul>"},{"location":"Changelog/#1048-2024-08-23","title":"10.4.8 - 2024-08-23","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the Storyteller delegate to not be writeable after the first initialization</li> </ul>"},{"location":"Changelog/#1047-2024-08-19","title":"10.4.7 - 2024-08-19","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug with the formatting of the ads targeting object</li> </ul>"},{"location":"Changelog/#1046-2024-08-16","title":"10.4.6 - 2024-08-16","text":"<p>Improvements:</p> <ul> <li>Fall back to navigator share API (if available) if the provided <code>onShareButtonTapped</code> function returns <code>null</code> or isn't a Promise</li> </ul>"},{"location":"Changelog/#1045-2024-07-30","title":"10.4.5 - 2024-07-30","text":"<p>Improvements:</p> <ul> <li>Pinned Stories now use the same styles as Live Stories (to match the native SDKs)</li> <li><code>clipActionText</code> and <code>clipActionUrl</code> properties are now recorded for Clip events</li> <li>Improved error handling when an invalid container ID is supplied</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the <code>completedStory</code> event not to be recorded if a Story was already read</li> <li>Fixed a bug where it was possible for the category update of an existing Story row to lead to a console error</li> </ul>"},{"location":"Changelog/#1044-2024-07-26","title":"10.4.4 - 2024-07-26","text":"<p>Improvements:</p> <ul> <li>Updated the correlator in ads requests URLs so that it's always unique</li> </ul>"},{"location":"Changelog/#1043-2024-07-17","title":"10.4.3 - 2024-07-17","text":"<p>Improvements:</p> <ul> <li>Updated the ads algorithm to keep requesting ads for a Story even if a previous request failed</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for overflow to be disabled when closing the Story player using the browser back button</li> </ul>"},{"location":"Changelog/#1042-2024-07-03","title":"10.4.2 - 2024-07-03","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for 1st-party ads to be requested from the wrong endpoint</li> </ul>"},{"location":"Changelog/#1041-2024-06-28","title":"10.4.1 - 2024-06-28","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for a read Story to be shown as unread when new pages were just added but the assets were still processing</li> </ul>"},{"location":"Changelog/#1040-2024-06-27","title":"10.4.0 - 2024-06-27","text":"<p>Improvements:</p> <ul> <li>Replaced the <code>liveChip.textColor</code> theme property with <code>liveChip.readTextColor</code> and <code>liveChip.unreadTextColor</code></li> <li>Replaced the <code>storyTiles.liveChip</code> theme properties with <code>storyTiles.rectangularTile.liveChip</code> and <code>storyTiles.circularTile.liveChip</code></li> <li>Added support for live clips in browsers that don't support HTTP Live Streaming</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the live chip inside the Clips player to use the default styles instead of the custom theme</li> <li>Fixed a bug where it was possible for the live chip inside the Stories player to use the default styles instead of the custom theme</li> </ul>"},{"location":"Changelog/#1036-2024-06-20","title":"10.3.6 - 2024-06-20","text":"<p>Improvements:</p> <ul> <li>Updated the ads logic to keep fetching ads for a Story even if a previous request failed</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the first ad in a Story to appear a page later than the provided frequency</li> </ul>"},{"location":"Changelog/#1035-2024-06-18","title":"10.3.5 - 2024-06-18","text":"<p>Improvements:</p> <ul> <li>Added support for some cookie banners that clear or update local storage when dismissed</li> </ul>"},{"location":"Changelog/#1034-2024-06-13","title":"10.3.4 - 2024-06-13","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the round Story cells to remain empty on Safari iOS 16.4 and below</li> </ul>"},{"location":"Changelog/#1033-2024-06-07","title":"10.3.3 - 2024-06-07","text":"<p>Improvements:</p> <ul> <li>Updated the maximum lines of the round Story cells titles so they adapt to the chosen line height</li> </ul>"},{"location":"Changelog/#1032-2024-06-06","title":"10.3.2 - 2024-06-06","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the round Story cells borders to get cropped</li> <li>Fixed a bug where it was possible for the round Story cells borders colours to not reflect the read/unread state</li> </ul>"},{"location":"Changelog/#1031-2024-05-31","title":"10.3.1 - 2024-05-31","text":"<p>Improvements:</p> <ul> <li>Improved console error logs when no Clips or Stories available</li> <li>Improved mouse scrolling experience for Clips on Firefox</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the first Story in a view to skip pre-loading for tenants with a lot of Stories</li> <li>Fixed a bug where it was possible for the ads action button destination to be displayed instead of the advertiser name if no advertiser name was provided</li> </ul>"},{"location":"Changelog/#1030-2024-05-15","title":"10.3.0 - 2024-05-15","text":"<p>New Features:</p> <ul> <li>Introduced first-party ads support</li> <li>Introduced linear-gradient support for the round cell borders</li> </ul> <p>Improvements:</p> <ul> <li>Improved initialization errors</li> <li>'New' chip are not shown on pinned Stories so as to match the native SDKs behaviors</li> <li>The tappable area to pause the Clips player has been increased</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for a viewed clip to display the 'new' chip</li> <li>Fixed a bug where it was possible for some of the buttons theme properties to not get applied</li> <li>Fixed a bug where it was possible for Stories to get cropped on some tablet screens</li> <li>Fixed a bug where it was possible for the Clips share amount to not persist on navigation</li> </ul>"},{"location":"Changelog/#1021-2024-05-02","title":"10.2.1 - 2024-05-02","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for some of the instructions theme properties to not get applied</li> </ul>"},{"location":"Changelog/#1020-2024-04-10","title":"10.2.0 - 2024-04-10","text":"<p>New Features:</p> <ul> <li>Added the <code>openCategory</code> method to Story views</li> <li>Added support for Clips read/unread ordering</li> <li>Added support for Clips locales using <code>Storyteller.User.setLocale</code></li> </ul> <p>Improvements:</p> <ul> <li>Removed Storyteller inline styles</li> <li>Updated ad events to use seconds (not milliseconds) for consistency with other events</li> <li>Clips players can now be closed by clicking on the background</li> <li>Improved transition between clips on Safari for smoother experience</li> <li>Adjusted the Story player to accommodate sticky elements like Smart App banners</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the Story lightbox not to open</li> <li>Fixed a bug where it was possible for the Story page to restart after sharing on Safari</li> <li>Fixed a bug where it was possible for the Story progress bars to transition from their previous state upon reopening</li> </ul>"},{"location":"Changelog/#1013-2024-04-16","title":"10.1.3 - 2024-04-16","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the Story player to load indefinitely after closing the instructions screen</li> </ul>"},{"location":"Changelog/#1012-2024-04-03","title":"10.1.2 - 2024-04-03","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for round story cells with hidden titles to be horizontally off-centre in Chromium browsers</li> </ul>"},{"location":"Changelog/#1011-2024-03-19","title":"10.1.1 - 2024-03-19","text":"<p>Improvements:</p> <ul> <li>If the <code>lists.row.scrollIndicatorInlineAlignment</code> theme property is set to <code>outside</code> and the row doesn't have enough items for the scroll indicators to be visible, the empty space where the indicator would normally sit has been removed</li> </ul>"},{"location":"Changelog/#1010-2024-03-08","title":"10.1.0 - 2024-03-08","text":"<p>New Features:</p> <ul> <li>The advertiser name property is now supported for AMPHTML ads</li> <li>Stories now don't preload by default (this can be overridden using the <code>configuration.preload</code> property at the list level)</li> <li>Added inline clips player component (<code>StorytellerClipsPlayerView</code>)</li> <li>The Story rows scroll indicator can now be moved outside of the carousel using the <code>lists.row.scrollIndicatorInlineAlignment</code> theme property</li> <li>The Story rows scroll indicator can now be horizontally aligned with the thumbnails (instead of the whole cell which includes the title) using the <code>storyTiles.circularTile.scrollIndicatorBlockAlignment</code> theme property</li> <li>The thickness of round cells borders is now configurable using the <code>storyTiles.circularTile.unreadStrokeWidth</code> and <code>storyTiles.circularTile.readStrokeWidth</code> theme properties</li> <li>Ad events are now recorded</li> </ul> <p>Improvements:</p> <ul> <li>Story players can now be closed by pressing the <code>Esc</code> button</li> <li>Story players can now be closed by clicking on the background</li> <li>Trying to initialize a Storyteller instance more than once will now throw an error</li> <li>Clicking on an already answered quiz option now moves the user to the next page</li> <li><code>OpenedReason</code> now has additional possible values: <code>tap</code> and <code>automaticPlayback</code></li> <li><code>DismissedReason</code> now has additional possible values: <code>backgroundTapped</code>, <code>skippedFinalPage</code>, <code>completedFinalPage</code>, and <code>backTapped</code></li> <li>The following enums used for building custom themes are now exposed: <code>Alignment</code>, <code>ButtonAlignment</code>, and <code>TextCase</code></li> <li>The <code>IListConfiguration</code> type is now exposed and can be used to set a list's configuration</li> <li>Updated the type of <code>IStorytellerDelegate</code> to make the <code>onUserActivityOccurred</code> callback optional</li> <li>Updated the type of <code>IStorytellerDelegate</code> to make <code>customTargeting</code> optional in <code>getAdConfig</code></li> <li>Grid thumbnails now use the most appropriate thumbnail size</li> <li>The clip player now automatically pauses on tab change</li> <li>If <code>playAllStories</code> is set to false and the next Story will be skipped, the next Story button is greyed out</li> <li>Various improvements to the clip player transitions and experience</li> <li>Various performance improvements to the Stories player on iOS</li> <li>Various improvements to the loading states and transitions</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for the player not to pause when pressing the share button on Safari</li> <li>Fixed a bug where it was possible for a Story page to get skipped after answering a poll</li> <li>Fixed a bug where it was possible for the <code>OpenedPage</code> event not to get triggered</li> <li>Fixed a bug where it was possible for the player to pause when a quiz question wasn't answered</li> <li>Fixed a bug where it was possible for a previously opened Story to appear briefly when opening another Story</li> <li>Fixed a bug where it was possible for Story audio to keep playing after the player was closed</li> <li>Fixed a bug where it was possible for a Story to show a grey screen when navigating backwards or quickly</li> <li>Fixed a bug where it was possible for the wrong <code>OpenedReason</code> to be recorded when opening a Story or Page</li> <li>Fixed a bug where it was possible for clip players to be appended to the DOM more than once on SPAs</li> <li>Fixed a bug where it was possible for the clip player back button to scroll users back to the top of the page</li> <li>Fixed a bug where it was possible for poll results to clash with the background</li> <li>Fixed a bug where it was possible for OneBox Stories not to autoplay in the Google app</li> <li>Fixed a bug where it was possible for the live chip position to be wrong when the row titles were hidden</li> </ul>"},{"location":"Changelog/#1004-2024-02-02","title":"10.0.4 - 2024-02-02","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for short image polls captions to overlap with the background</li> </ul>"},{"location":"Changelog/#1003-2024-01-31","title":"10.0.3 - 2024-01-31","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for OneBox Stories not to send events analytics to Amplitude</li> </ul>"},{"location":"Changelog/#1002-2024-01-26","title":"10.0.2 - 2024-01-26","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a bug where it was possible for OneBox Stories not to send engagement units events analytics</li> </ul>"},{"location":"Changelog/#1001-2024-01-10","title":"10.0.1 - 2024-01-10","text":"<p>Bug Fixes:</p> <ul> <li>Fixed a console error about <code>navigator</code> being undefined</li> <li>Fixed a bug where the gradient behind the Story titles on rectangular tiles didn't respect padding preferences</li> </ul>"},{"location":"Changelog/#1000-2024-01-10","title":"10.0.0 - 2024-01-10","text":"<p>New Features:</p> <ul> <li>Added support for Clips</li> <li>Introduced the <code>configuration</code> object for list views</li> <li>Implemented tracking for ad events</li> </ul> <p>Improvements:</p> <ul> <li>Added support for <code>instanceMethod</code> and <code>escapeKeyPressed</code> in the analytics events' <code>DismissedReason</code> property</li> <li>Added support for <code>tap</code> and <code>automaticPlayback</code> in the analytics events' <code>OpenedReason</code> property</li> <li>Added <code>isInitialized</code> and <code>isPlayerVisible</code> properties to the global Storyteller instance</li> <li>Added the <code>dismissPlayer</code> method to the global Storyteller instance</li> <li>Added the <code>enableEventTracking</code> and <code>disableEventTracking</code> methods to the global Storyteller instance</li> <li>Added the <code>enableLogging</code> method to the global Storyteller instance</li> <li>Added <code>IListViewDelegate</code> type export</li> <li>Moved the <code>openPage</code> and <code>openStory</code> methods from the list views to the global Storyteller instance</li> <li>Renamed the <code>onShareButtonClicked</code> callback to <code>onShareButtonTapped</code> and moved it to the global Storyteller delegate</li> <li>Renamed the <code>onStoriesDataLoadStarted</code> callback to <code>onDataLoadStarted</code></li> <li>Renamed the <code>onStoriesDataLoadComplete</code> callback to <code>onDataLoadComplete</code></li> <li>Renamed the <code>onStoryDismissed</code> callback to <code>onPlayerDismissed</code></li> <li>Moved the <code>getAdConfig</code> method to the global Storyteller delegate</li> <li>Moved the <code>onUserActivityOccurred</code> callback to the global Storyteller delegate</li> <li>Removed the <code>tileBecameVisible</code> callback</li> <li>Removed the <code>onError</code> callback</li> <li>Updated list views to derive their basename from their categories or collection</li> <li>Improved dark mode support and default styles</li> <li>Various performance and playback improvements</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed a bug where the <code>OpenedPage</code> event did not fire on Stories with a single Page</li> <li>Fixed a bug where the <code>SkippedStory</code> event did not fire when the final Page of a Story was skipped</li> <li>Resolved playback issues on quizz Pages</li> </ul>"},{"location":"Changelog/#894-2023-12-18","title":"8.9.4 - 2023-12-18","text":"<p>Improvements:</p> <ul> <li>Adding support for dark mode placeholders by using the <code>lists.backgroundColor</code> theme property to set the placeholder styles</li> <li>Preventing Content Layout Shift when loading grid items</li> </ul>"},{"location":"Changelog/#893-2023-12-08","title":"8.9.3 - 2023-12-08","text":"<p>Improvements:</p> <ul> <li>Adding <code>title.show</code> theme property to show/hide Story titles on all tiles</li> <li>Removed <code>circularTile.title.hide</code> theme property</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for round Story tiles with hidden titles to get cropped</li> </ul>"},{"location":"Changelog/#892-2023-12-01","title":"8.9.2 - 2023-12-01","text":"<p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for the player to load indefinitely after closing the instructions screen</li> </ul>"},{"location":"Changelog/#891-2023-11-30","title":"8.9.1 - 2023-11-30","text":"<p>Bug Fixes:</p> <ul> <li>Adding TypeScript declaration file export to <code>package.json</code></li> </ul>"},{"location":"Changelog/#890-2023-11-22","title":"8.9.0 - 2023-11-22","text":"<p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for auto-advancing ads to not show a progress bar</li> <li>Fixing a bug where it was possible for action buttons to open the wrong URL in Stories with multiple action buttons</li> </ul>"},{"location":"Changelog/#887-2023-10-26","title":"8.8.7 - 2023-10-26","text":"<p>Bug Fixes:</p> <ul> <li>fixing a bug where it was possible for stories not to play when the instructions screen was hidden via the theme</li> </ul>"},{"location":"Changelog/#886-2023-10-25","title":"8.8.6 - 2023-10-25","text":"<p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for OpenedStory events not to be fired in certain scenarios</li> <li>Fixing a bug where it was possible for OpenedPage events not to be fired in certain scenarios</li> <li>Fixing a bug where it was possible for PreviousPage events to be fired at an incorrect moment</li> <li>Fixing a bug where it was possible for the story player to be incorrectly aligned on certain mobile browsers</li> <li>Fixing a bug where it was possible for playback to stall on certain mobile browsers</li> </ul>"},{"location":"Changelog/#885-2023-10-24","title":"8.8.5 - 2023-10-24","text":"<p>Improvements:</p> <ul> <li>Moving the Action button below the player on desktop</li> <li>Reducing the size of the Action button on mobile browsers to reduce the chance of collision with content</li> </ul>"},{"location":"Changelog/#884-2023-10-17","title":"8.8.4 - 2023-10-17","text":"<p>Improvements:</p> <ul> <li>Fixing the category query parameter</li> </ul>"},{"location":"Changelog/#883-2023-10-13","title":"8.8.3 - 2023-10-13","text":"<p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for Current Category to be reported as empty</li> </ul>"},{"location":"Changelog/#882-2023-10-13","title":"8.8.2 - 2023-10-13","text":"<p>Improvements:</p> <ul> <li>Added support for returning <code>externalId</code></li> </ul> <p>Bug Fixes:</p> <ul> <li>When no Category is matched, <code>CurrentCategory</code> no longer reports <code>\"Home\"</code></li> </ul>"},{"location":"Changelog/#881-2023-10-12","title":"8.8.1 - 2023-10-12","text":"<p>Improvements:</p> <ul> <li>Fixing a bug where it was possible for <code>externalId</code> for Categories for Ads Targeting</li> <li>Fixing a bug where it was possible for Current Category to be reported incorrectly for Analytics</li> </ul>"},{"location":"Changelog/#880-2023-10-11","title":"8.8.0 - 2023-10-11","text":"<p>New Features:</p> <ul> <li>Adding fixed story order support</li> <li>Adding pinned story support</li> </ul> <p>Improvements:</p> <ul> <li>Fixing Story navigation bugs</li> <li>Fixing instruction page bugs</li> <li>Adding missing <code>title</code> attribute in iframes</li> </ul>"},{"location":"Changelog/#870-2023-10-05","title":"8.7.0 - 2023-10-05","text":"<p>New Features:</p> <ul> <li>Adding support for ads between pages</li> </ul> <p>Improvements:</p> <ul> <li>Adding <code>SkippedPage</code> Analytics Event</li> <li>Adding <code>CompletedPage</code> Analytics Event</li> <li>Adding <code>Page Title</code> to all events</li> <li>Adding missing event properties</li> <li>Updating Story Title display</li> <li>Adding missing <code>alt</code> attributes</li> <li>Fixing images aspect ratio errors</li> </ul>"},{"location":"Changelog/#860-2023-09-20","title":"8.6.0 - 2023-09-20","text":"<p>Improvements:</p> <ul> <li>Removing the # from the URL when closing a Story.</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing a muting/unmuting bug when going back into a Story.</li> <li>Fixing errors coming from Google Ad Manager.</li> </ul>"},{"location":"Changelog/#853-2023-09-05","title":"8.5.3 - 2023-09-05","text":"<p>Improvements:</p> <ul> <li>Validate <code>AdConfig</code> before passing it to Story View</li> </ul>"},{"location":"Changelog/#852-2023-08-30","title":"8.5.2 - 2023-08-30","text":"<p>Bug Fixes:</p> <ul> <li>Fixed module exports</li> </ul>"},{"location":"Changelog/#851-2023-08-29","title":"8.5.1 - 2023-08-29","text":"<p>Bug Fixes:</p> <ul> <li>Fixed Storyteller usage in Jest tests</li> </ul>"},{"location":"Changelog/#850-2023-08-17","title":"8.5.0 - 2023-08-17","text":"<p>New Features:</p> <ul> <li>Adding <code>useGoogleWebStoryUrls</code> parameter to <code>StorytellerStoriesGridView</code></li> </ul> <p>Improvements:</p> <ul> <li>Reduced SDK budle size by 50%, leading to faster app performance.</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for the navigation arrows on desktop to not appear.</li> <li>Fixing a bug where it was possible for Story transition animations to not appearing.</li> <li>Fixing a bug where it was possible for Stories to fail to open when opened via a URL.</li> </ul>"},{"location":"Changelog/#842-2023-07-31","title":"8.4.2 - 2023-07-31","text":"<p>New Features:</p> <ul> <li>Adding the ability to open a fully AMPHTML compatible version of stories when selecting an item from a StorytellerStoriesRowView</li> </ul> <p>Bug Fixes:</p> <ul> <li>In certain situations, the <code>OpenedStory</code> and <code>OpenedPage</code> events might not fire. This is now fixed.</li> </ul>"},{"location":"Changelog/#841-2023-07-07","title":"8.4.1 - 2023-07-07","text":"<p>New Features:</p> <ul> <li>Allow the ability to set a <code>theme</code> on an individual StorytellerStoriesRowView or StorytellerStoriesGridView</li> </ul>"},{"location":"Changelog/#840-2023-06-30","title":"8.4.0 - 2023-06-30","text":"<p>Improvements:</p> <ul> <li>Standardizing the behavior of quizzes with our native SDKs</li> <li>Adding additional analytics properties</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing a bug where it was possible for the \"Share your Result\" button on quizzes to be black in Safari</li> <li>Fixing a bug where videos could fail to play if a user hadn't interacted with the browser</li> <li>Fixing a bug where it was possible for a Page's sound to continue playing after the Story player was dismissed</li> </ul>"},{"location":"Changelog/#820-2023-06-23","title":"8.2.0 - 2023-06-23","text":"<p>New Features:</p> <ul> <li>Adding support for Audience Targeting and Personalization - see Users for more information</li> </ul> <p>Improvements:</p> <ul> <li>Adding additional analytics properties</li> </ul>"},{"location":"Changelog/#810-2023-06-01","title":"8.1.0 - 2023-06-01","text":"<p>Improvements:</p> <ul> <li>Internal state management and minor bugfixes</li> </ul>"},{"location":"Changelog/#800-2023-04-26","title":"8.0.0 - 2023-04-26","text":"<p>New Features:</p> <ul> <li>Added a rectangular tile gradient theme property</li> <li>Added support for <code>customInstanceHost</code></li> </ul> <p>Improvements:</p> <ul> <li>Added support for compiling on case-sensitive filesystems</li> <li>Engagement units are now fetched from the view instead of the API</li> <li>Updated the quiz renderer to use a more specific grid layer selector</li> </ul>"},{"location":"Changelog/#792-2023-04-17","title":"7.9.2 - 2023-04-17","text":"<p>New Features:</p> <ul> <li>Adding <code>useGoogleWebStoryUrls</code> parameter to <code>StorytellerListView</code></li> </ul>"},{"location":"Changelog/#791-2023-01-17","title":"7.9.1 - 2023-01-17","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug causing the skip story buttons to not appear on Safari</li> </ul>"},{"location":"Changelog/#790-2023-01-16","title":"7.9.0 - 2023-01-16","text":"<p>Improvements:</p> <ul> <li>Add theme property to hide the gradient on rectangular thumbnails</li> </ul>"},{"location":"Changelog/#785-2023-01-13","title":"7.8.5 - 2023-01-13","text":"<p>Bug Fixes:</p> <ul> <li>Stop the flash of images when coming back from swipe up</li> </ul>"},{"location":"Changelog/#784-2023-01-12","title":"7.8.4 - 2023-01-12","text":"<p>Bug Fixes:</p> <ul> <li>Story player improvements</li> </ul>"},{"location":"Changelog/#782-2022-12-13","title":"7.8.2 - 2022-12-13","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug where the PreviousPage event would not fire</li> <li>Fixing bug where the SkippedStory event would not fire</li> </ul>"},{"location":"Changelog/#781-2022-12-13","title":"7.8.1 - 2022-12-13","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug where the player would freeze when opened</li> <li>Fixing bug where the PreviousPage event would not fire</li> </ul>"},{"location":"Changelog/#780-2022-12-05","title":"7.8.0 - 2022-12-05","text":"<p>Bug Fixes:</p> <ul> <li>Ensuring circular live story border matches theme color</li> <li>Improving loading behavior when opening stories</li> </ul>"},{"location":"Changelog/#771-2022-11-09","title":"7.7.1 - 2022-11-09","text":"<p>Bug Fixes:</p> <ul> <li>Fixing <code>font</code> theme property</li> <li>Fixing <code>instructions.icons</code> theme property</li> </ul>"},{"location":"Changelog/#770-2022-09-28","title":"7.7.0 - 2022-09-28","text":"<p>Improvements:</p> <ul> <li>Allow quizzes to be rendered outside stories</li> <li>Adding <code>showWebStoriesIcon</code> theme property</li> </ul>"},{"location":"Changelog/#760-2022-09-23","title":"7.6.0 - 2022-09-23","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug where thumbnails would sometimes fail to load</li> </ul> <p>Improvements:</p> <ul> <li>Adding <code>displayLimit</code> to rows and grids</li> <li>Exposing <code>contentLength</code> in user activity delegate callback</li> </ul>"},{"location":"Changelog/#750-2022-08-29","title":"7.5.0 - 2022-08-29","text":"<p>Bug Fixes:</p> <ul> <li>Lazy load Story tile thumbnails</li> <li>Fixing issue where the navigation buttons could disappear</li> <li>Stop player going back 2 Stories when back button pressed</li> </ul> <p>Improvements:</p> <ul> <li>Improve caching for static assets</li> </ul>"},{"location":"Changelog/#745-2022-08-22","title":"7.4.5 - 2022-08-22","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug with scroll indicator fade theming</li> <li>Fixing bug when applying corner radius theme property</li> </ul>"},{"location":"Changelog/#743-2022-08-17","title":"7.4.3 - 2022-08-17","text":"<p>Bug Fixes:</p> <ul> <li>Fixing quiz score placement when sharing disabled</li> <li>Fixing bug where instructions screen took multiple clicks to dismiss</li> </ul>"},{"location":"Changelog/#742-2022-08-17","title":"7.4.2 - 2022-08-17","text":"<p>Bug Fixes:</p> <ul> <li>Don't reorder Stories when player is closed</li> <li>Fix NPM type definitions</li> </ul> <p>Improvements:</p> <ul> <li>Use simple HTTP Requests</li> </ul>"},{"location":"Changelog/#741-2022-07-29","title":"7.4.1 - 2022-07-29","text":"<p>New Features:</p> <ul> <li>Adding <code>openStory</code> and <code>openPage</code> methods</li> </ul>"},{"location":"Changelog/#740-2022-07-29","title":"7.4.0 - 2022-07-29","text":"<p>New Features:</p> <ul> <li>Support CommonJS and ESM</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing live chip theme issues</li> </ul>"},{"location":"Changelog/#735-2022-07-15","title":"7.3.5 - 2022-07-15","text":"<p>Bug Fixes:</p> <ul> <li>Don't show share results button if share API not available</li> <li>Fixing bug when returning from swipe up</li> <li>Make sure <code>externalApp</code> swipe ups are recorded correctly</li> </ul>"},{"location":"Changelog/#734-2022-07-13","title":"7.3.4 - 2022-07-13","text":"<p>Improvements:</p> <ul> <li>Improving support for older browsers</li> </ul>"},{"location":"Changelog/#733-2022-07-11","title":"7.3.3 - 2022-07-11","text":"<p>Bug Fixes:</p> <ul> <li>Polls theme fixes</li> </ul>"},{"location":"Changelog/#731-2022-07-08","title":"7.3.1 - 2022-07-08","text":"<p>Improvements:</p> <ul> <li>Make sure player Stories reorder when player closed</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing corrupt svg console errors</li> </ul>"},{"location":"Changelog/#730-2022-06-23","title":"7.3.0 - 2022-06-23","text":"<p>Deprecation and Changes:</p> <ul> <li>Removing <code>showStoryTitle</code> theme property</li> <li>Adding <code>showStoryIcon</code> theme property</li> </ul>"},{"location":"Changelog/#724-2022-06-20","title":"7.2.4 - 2022-06-20","text":"<p>Improvements:</p> <ul> <li>Improving open Story transitions</li> <li>Hide Quiz share button when share buttons hidden</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing issue with new indicator always showing on rectangular tiles</li> </ul>"},{"location":"Changelog/#722-2022-06-01","title":"7.2.2 - 2022-06-01","text":"<p>Bug Fixes:</p> <ul> <li>Fixing issues with NPM type definitions</li> </ul>"},{"location":"Changelog/#721-2022-05-31","title":"7.2.1 - 2022-05-31","text":"<p>Bug Fixes:</p> <ul> <li>Stop scroll to top when player closed</li> </ul>"},{"location":"Changelog/#720-2022-05-13","title":"7.2.0 - 2022-05-13","text":"<p>Bug Fixes:</p> <ul> <li>Fixing issues with NPM package</li> </ul>"},{"location":"Changelog/#712-2022-05-12","title":"7.1.2 - 2022-05-12","text":"<p>Improvements:</p> <ul> <li>Updating package.json</li> </ul>"},{"location":"Changelog/#711-2022-05-11","title":"7.1.1 - 2022-05-11","text":"<p>New Features:</p> <ul> <li>Added NPM support</li> </ul>"},{"location":"Changelog/#710-2022-05-02","title":"7.1.0 - 2022-05-02","text":"<p>New Features:</p> <ul> <li>Added support for Live Stories</li> </ul>"},{"location":"Changelog/#700-2022-04-07","title":"7.0.0 - 2022-04-07","text":"<p>New Features:</p> <ul> <li>Added support for Trivia Quizzes</li> </ul> <p>Improvements:</p> <ul> <li>Made implementing custom themes even easier</li> </ul>"},{"location":"Changelog/#220-2022-03-23","title":"2.2.0 - 2022-03-23","text":"<p>Improvements:</p> <ul> <li>Hide share button on browsers that don't support <code>navigator.share</code></li> <li>Make <code>externalId</code> optional</li> <li>Allow Ad frequency to be configured</li> </ul>"},{"location":"Changelog/#210-2022-03-11","title":"2.1.0 - 2022-03-11","text":"<p>Improvements:</p> <ul> <li>Adjust tile height to fill parent container</li> <li>Send <code>pollAnswerId</code> in analytics events</li> <li>Send all properties to analytics endpoint</li> </ul>"},{"location":"Changelog/#201-2022-02-16","title":"2.0.1 - 2022-02-16","text":"<p>Bug Fixes:</p> <ul> <li>Fixing Story Page issues</li> </ul>"},{"location":"Changelog/#200-2022-02-09","title":"2.0.0 - 2022-02-09","text":"<p>Improvements:</p> <ul> <li>Adding Grid Layout</li> <li>Theme updates</li> </ul> <p>New Features:</p> <ul> <li>Adding support for unread indicator gradient</li> </ul>"},{"location":"Changelog/#1171-2022-01-18","title":"1.17.1 - 2022-01-18","text":"<p>Improvements:</p> <ul> <li>Improving swipe behavior</li> <li>Show navigation arrows on touchscreen laptops</li> </ul> <p>Bug Fixes:</p> <ul> <li>Stopping JSONParseErrors being thrown for empty responses</li> <li>Fixing missing API key 401s</li> </ul>"},{"location":"Changelog/#1170-2021-11-19","title":"1.17.0 - 2021-11-19","text":"<p>New Features:</p> <ul> <li>Added full support for Categories</li> <li>Added support for ads</li> </ul>"},{"location":"Changelog/#1160-2021-11-02","title":"1.16.0 - 2021-11-02","text":"<p>New Features:</p> <ul> <li>Added the ability to swipe down to dismiss a Story</li> <li>Added the ability for share links to open a specific Page (instead of just the first Page in the Story)</li> <li>Added a <code>playAllStories</code> option to the theme which will not exit the Story player when the user reaches the end of their unread Stories - but rather keep them in the Stories experience until they see every Story in the row</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixed an issue which could cause Polls not to display in certain scenarios</li> </ul>"},{"location":"Changelog/#1150-2021-10-22","title":"1.15.0 - 2021-10-22","text":"<p>Improvements:</p> <ul> <li>Hiding 'i' button when video fails to play</li> </ul> <p>Bug Fixes:</p> <ul> <li>Stop video failed to play message appearing when a video successfully plays</li> </ul> <p>New Features:</p> <ul> <li>Recording share success events</li> </ul>"},{"location":"Changelog/#1140-2021-10-21","title":"1.14.0 - 2021-10-21","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug where Poll answer percentages display incorrectly</li> </ul>"},{"location":"Changelog/#1130-2021-10-19","title":"1.13.0 - 2021-10-19","text":"<p>Improvements:</p> <ul> <li>Preventing background media from being cropped</li> </ul>"},{"location":"Changelog/#1120-2021-10-18","title":"1.12.0 - 2021-10-18","text":"<p>Bug Fixes:</p> <ul> <li>Using the correct value for <code>storyReadStatus</code> in analytic events</li> <li>Fixing issue where Story titles are shared/duplicate sharing URLs are shared when tapping share button</li> </ul> <p>Improvements:</p> <ul> <li>Adding information about <code>VotedPoll</code> event to the docs</li> <li>Updating to open Story immediately when tapping/clicking Story tile instead of showing loading spinners</li> </ul>"},{"location":"Changelog/#1110-2021-10-15","title":"1.11.0 - 2021-10-15","text":"<p>Bug Fixes:</p> <ul> <li>Fixing sharing instructions issues</li> </ul>"},{"location":"Changelog/#1100-2021-10-12","title":"1.10.0 - 2021-10-12","text":"<p>Improvements:</p> <ul> <li>Removes the border around buttons in the Story player</li> </ul>"},{"location":"Changelog/#190-2021-10-07","title":"1.9.0 - 2021-10-07","text":"<p>Bug Fixes:</p> <ul> <li>Fixing bug where users can vote for a Poll more than once</li> </ul>"},{"location":"Changelog/#180-2021-10-05","title":"1.8.0 - 2021-10-05","text":"<p>Improvements:</p> <ul> <li>Adding theme option to hide Story titles</li> </ul> <p>Bug Fixes:</p> <ul> <li>Persisting mute state throughout Stories</li> <li>Fixing CORS issues</li> </ul>"},{"location":"Changelog/#170-2021-09-24","title":"1.7.0 - 2021-09-24","text":"<p>Bug Fixes:</p> <ul> <li>Stopping the wrong Story from being shown briefly when opening a share link</li> <li>Disabling the 'previous page' button on the first Page of the first Story</li> <li>Fixing issue where Story row would not load on iOS 12</li> </ul>"},{"location":"Changelog/#160-2021-09-23","title":"1.6.0 - 2021-09-23","text":"<p>Improvements:</p> <ul> <li>Always displaying the mute/unmute icon in player</li> <li>Adding text property to <code>onShareButtonClicked()</code> delegated method</li> <li>Allow 3 lines for the Story title when using circular tiles</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing instructions screen layout and icons on desktop</li> <li>Fixing issue with missing navigation arrows and black background when refreshing/arriving from shared link</li> </ul>"},{"location":"Changelog/#150-2021-09-17","title":"1.5.0 - 2021-09-17","text":"<p>Bug Fixes:</p> <ul> <li>Stop player closing when navigating backwards</li> <li>Sort all Story rows when player is closed</li> <li>Stop player from continuing in background after being closed</li> </ul> <p>New Features:</p> <ul> <li>Adding share delegate method</li> <li>Adding docs for share callback</li> </ul> <p>Improvements:</p> <ul> <li>Hide share button if <code>navigator.share</code> doesn't exist</li> <li>Don't hide share button if <code>onShareButtonClick</code> callback is defined</li> </ul>"},{"location":"Changelog/#140-2021-09-16","title":"1.4.0 - 2021-09-16","text":"<p>Bug Fixes:</p> <ul> <li>Fixing Poll styling</li> <li>Fixing ad overlay appearing over Story view</li> </ul>"},{"location":"Changelog/#130-2021-09-09","title":"1.3.0 - 2021-09-09","text":"<p>Bug Fixes:</p> <ul> <li>Fixing desktop player not pausing on share</li> <li>Fixing left scroll arrow</li> <li>Only show read Stories and fix player opening unexpectedly</li> <li>Don't open player until correct Story has loaded</li> <li>Fixing bug when opening same Story after dismissing it</li> <li>Setting opacity on tile loading</li> <li>Fixing style import</li> <li>Hide mute/unmute text</li> </ul> <p>New Features:</p> <ul> <li>Adding <code>tileLoading</code> state to tiles</li> </ul>"},{"location":"Changelog/#120-2021-09-07","title":"1.2.0 - 2021-09-07","text":"<p>New Features:</p> <ul> <li>Adding properties to row theme</li> </ul> <p>Bug Fixes:</p> <ul> <li>Fixing instruction icons</li> </ul> <p>Deprecations and Changes:</p> <ul> <li>Switch to using query string params instead of headers in API requests</li> <li>Updating row theme docs</li> </ul>"},{"location":"Changelog/#110-2021-09-02","title":"1.1.0 - 2021-09-02","text":"<p>Bug Fixes:</p> <ul> <li>Fixing Poll styling</li> <li>Fixing ad overlay appearing over Story view</li> </ul>"},{"location":"OpenPlayer/","title":"Open a player programmatically","text":"<p>Open a Story or Clips player from your own button, link, or route instead of a tile. These methods are on <code>Storyteller.sharedInstance</code>. Each one returns a promise that rejects when the SDK can't open the content. Call them after <code>initialize</code> resolves.</p> <pre><code>const openFeaturedStory = async () =&gt; {\n  try {\n    await Storyteller.sharedInstance.openStory('story-id');\n  } catch (error) {\n    console.error('The Story could not be opened.', error);\n  }\n};\n\ndocument\n  .getElementById('featured-story-button')\n  ?.addEventListener('click', openFeaturedStory);\n</code></pre> <p>The SDK first looks for the content in the views on your page and opens it in that view's player. It uses only views whose player URLs are turned on, which means the <code>disableUrls</code> theme setting is <code>false</code>. If no view on the page has the content, the SDK loads it from Storyteller and opens it in a default player. Either way, the SDK opens the player by setting the page's hash URL, such as <code>#stories/story-id</code>, and the promise resolves at that point. See <code>basename</code> for the URL format.</p>"},{"location":"OpenPlayer/#open-a-story","title":"Open a Story","text":""},{"location":"OpenPlayer/#openstory","title":"openStory","text":"<p>Opens a Story by its ID.</p> <pre><code>await Storyteller.sharedInstance.openStory('story-id');\n</code></pre> <p>Full signature: <code>openStory</code>.</p>"},{"location":"OpenPlayer/#openstorybyexternalid","title":"openStoryByExternalId","text":"<p>Opens a Story by its external ID.</p> <pre><code>await Storyteller.sharedInstance.openStoryByExternalId('story-external-id');\n</code></pre> <p>Full signature: <code>openStoryByExternalId</code>.</p>"},{"location":"OpenPlayer/#openpage","title":"openPage","text":"<p>Opens the Story that contains a Page, starting at that Page.</p> <pre><code>await Storyteller.sharedInstance.openPage('page-id');\n</code></pre> <p>Full signature: <code>openPage</code>.</p>"},{"location":"OpenPlayer/#opencategory","title":"openCategory","text":"<p>Opens the Story player for a Category. Pass a Story ID as the second argument to start at that Story; otherwise, the first Story in the Category opens.</p> <pre><code>await Storyteller.sharedInstance.openCategory('category-id', 'story-id');\n</code></pre> <p>Full signature: <code>openCategory</code>.</p>"},{"location":"OpenPlayer/#open-clips","title":"Open Clips","text":""},{"location":"OpenPlayer/#opencollection","title":"openCollection","text":"<p>Opens the Clips player for a collection. Pass a <code>destination</code> to start at a Clip, or at the first Clip in a Clip Category. Otherwise, the first Clip in the collection opens.</p> <pre><code>await Storyteller.sharedInstance.openCollection('collection-id');\n\nawait Storyteller.sharedInstance.openCollection('collection-id', {\n  clipId: 'clip-id',\n});\n\nawait Storyteller.sharedInstance.openCollection('collection-id', {\n  categoryId: 'clip-category-id',\n});\n</code></pre> <p>When the user arrived through a deep link, pass <code>Storyteller.OpenedReason.deepLink</code> as the third argument so analytics events report <code>deepLink</code> as the reason:</p> <pre><code>await Storyteller.sharedInstance.openCollection(\n  'collection-id',\n  { clipId: 'clip-id' },\n  Storyteller.OpenedReason.deepLink\n);\n</code></pre> <p>Full signature: <code>openCollection</code>.</p>"},{"location":"OpenPlayer/#openclipbyexternalid","title":"openClipByExternalId","text":"<p>Opens the Clips player for a collection, at the Clip with this external ID.</p> <pre><code>await Storyteller.sharedInstance.openClipByExternalId(\n  'collection-id',\n  'clip-external-id'\n);\n</code></pre> <p>Full signature: <code>openClipByExternalId</code>.</p>"},{"location":"OpenPlayer/#close-the-player","title":"Close the player","text":"<p>Call <code>dismissPlayer</code> to close the open Story or Clips player, for example when your application navigates away. Pass <code>true</code> to play the close animation. If no player is open, the call does nothing. It doesn't close a <code>StorytellerEmbeddedClipsPlayerView</code>.</p> <pre><code>if (Storyteller.sharedInstance.isPlayerVisible) {\n  Storyteller.sharedInstance.dismissPlayer(true);\n}\n</code></pre> <p>Full signature: <code>dismissPlayer</code>.</p>"},{"location":"OpenPlayer/#handle-errors","title":"Handle errors","text":"<p>Wrap each call in <code>try</code>/<code>catch</code>, or add <code>.catch()</code>, so that a rejected promise doesn't go unhandled. The rejection value can be an <code>Error</code> or a string.</p> Method When the content is missing <code>openStory</code>, <code>openStoryByExternalId</code> Rejects when the Story request fails, or with a string when no Story has the ID. <code>openPage</code> Rejects when the SDK can't load a Story that contains the Page. <code>openCategory</code> Rejects when the SDK can't load the Category, or the Category has no Stories. If <code>storyId</code> isn't in the Category, the first Story opens instead. <code>openCollection</code> Rejects when the SDK can't load the collection, or the collection has no Clips. If the <code>destination</code> Clip or Category isn't in the collection, the first Clip opens instead. <code>openClipByExternalId</code> Rejects when the SDK can't load the collection, or with a string when the collection has no Clip with the external ID. <p>When the SDK opens the first Story or Clip instead of the one you asked for, it logs a message. Call <code>enableLogging</code> to see it in the browser console.</p>"},{"location":"OpenPlayer/#next-steps","title":"Next steps","text":"<ul> <li>Use additional SDK methods: full signatures for every method on this page</li> <li>Integrate analytics: the events that each player sends when it opens</li> <li>Configure views: hash URLs and <code>basename</code></li> </ul>"},{"location":"PrivacyAndTracking/","title":"Control privacy and tracking","text":"<p>Use <code>Storyteller.sharedInstance.eventTrackingOptions</code> to apply your users' privacy and consent choices. Each option turns off one kind of tracking or storage. Set the options before you call <code>initialize</code>, so the SDK follows them from its first request. You can assign new options at any time, for example when a user changes their consent.</p> JavaScriptTypeScript <pre><code>Storyteller.sharedInstance.eventTrackingOptions = {\n  disabledFunctionalFeatures: ['all'],\n  enableAdTracking: false,\n  enableFullVideoAnalytics: false,\n  enableFunctionalCookies: false,\n  enablePersonalization: false,\n  enableRemoteViewingStore: false,\n  enableStorytellerTracking: false,\n  enableUserActivityTracking: false,\n};\n</code></pre> <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport {\n  StorytellerTrackedFunctionalFeature,\n  type StorytellerEventTrackingOptions,\n} from '@getstoryteller/storyteller-sdk-javascript';\n\nconst eventTrackingOptions: StorytellerEventTrackingOptions = {\n  disabledFunctionalFeatures: [StorytellerTrackedFunctionalFeature.all],\n  enableAdTracking: false,\n  enableFullVideoAnalytics: false,\n  enableFunctionalCookies: false,\n  enablePersonalization: false,\n  enableRemoteViewingStore: false,\n  enableStorytellerTracking: false,\n  enableUserActivityTracking: false,\n};\n\nStoryteller.sharedInstance.eventTrackingOptions = eventTrackingOptions;\n</code></pre> <p>By default, <code>disabledFunctionalFeatures</code> is an empty array and every other option is <code>true</code>.</p> <p>Each assignment replaces all options. An option you leave out returns to its default, so pass every option each time.</p>"},{"location":"PrivacyAndTracking/#disabled-functional-features","title":"Disabled functional features","text":"<p><code>disabledFunctionalFeatures</code> accepts an array of the following <code>StorytellerTrackedFunctionalFeature</code> values. In a script tag, pass the string values, for example <code>['pollVotes']</code>. The <code>StorytellerTrackedFunctionalFeature</code> enum is available only from the npm package.</p> Item name Description <code>all</code> Disables all of the options below. <code>clipLikes</code> Disables Clip like tracking. If a user likes a Clip, the UI updates, but if they swipe away and come back to that Clip, it appears unliked again. <code>clipShares</code> Disables Clip share tracking. If a user shares a Clip, the UI updates, but if they swipe away and come back to that Clip, the share count returns to its value before the user shared it. <code>clipViewedStatus</code> Disables Clip viewed tracking, and all Clips appear as not viewed. The SDK also stops sending the IDs of recently viewed Clips with Clips requests. <code>pageReadStatus</code> Disables Story read tracking, and all Stories appear as unread. <code>pollVotes</code> Disables Poll vote tracking. If a user votes in a Poll, the UI updates, but when they go to another Page and come back, they can vote in the Poll again. <code>triviaQuizAnswers</code> Disables Quiz answer tracking and hides the results Page. If a user answers a Quiz question, the UI updates, but when they go to another Page and come back, they can answer it again."},{"location":"PrivacyAndTracking/#ad-tracking","title":"Ad tracking","text":"<p>Set <code>enableAdTracking</code> to <code>false</code> to:</p> <ul> <li>stop sending ad events to Storyteller analytics</li> <li>leave ad events out of the <code>onUserActivityOccurred</code> callback</li> <li>leave information about the current Story or Clip out of ad requests</li> <li>leave the <code>publisherProvidedId</code> that your <code>getAdConfig</code> callback returns out   of ad requests</li> </ul> <p>The <code>customTargeting</code> values that your <code>getAdConfig</code> callback returns are still sent. Leave them out yourself when a user opts out of ad tracking.</p>"},{"location":"PrivacyAndTracking/#full-video-analytics","title":"Full video analytics","text":"<p>When <code>enableFullVideoAnalytics</code> is <code>true</code>, events sent to the <code>onUserActivityOccurred</code> callback include detailed video information, such as Story titles, Clip titles, Story IDs, and Clip IDs.</p> <p>When it is <code>false</code>, the SDK sets these fields to <code>null</code> for Video Privacy Protection Act (VPPA) compliance:</p> <ul> <li><code>storyId</code>, <code>storyTitle</code>, <code>storyDisplayTitle</code></li> <li><code>clipId</code>, <code>clipTitle</code></li> <li><code>pageId</code>, <code>pageTitle</code></li> </ul> <p>This lets you comply with video privacy regulations and still receive engagement events. All other event data, such as user interactions, durations, and event types, is still included.</p>"},{"location":"PrivacyAndTracking/#functional-cookies-and-local-storage-items","title":"Functional cookies and local storage items","text":"<p>Set <code>enableFunctionalCookies</code> to <code>false</code> to:</p> <ul> <li>turn off read status tracking</li> <li>stop storing user IDs</li> <li>turn off Storyteller analytics, except the events listed in   Storyteller tracking</li> <li>stop storing non-essential items in local storage, and remove the ones the   SDK stored before</li> </ul> <p>The table below lists every item the SDK stores in the browser's local storage. The SDK stores items marked Always stored even when <code>enableFunctionalCookies</code> is <code>false</code>, because it needs them to work. For example, Stories run in iframes, and the Story player and Story Pages share data through these items.</p> Item name Description User data? Always stored? <code>Storyteller.apiKey</code> The API key passed to <code>initialize</code>. No Yes <code>Storyteller.captionsEnabled</code> The user's caption choice, shared by Stories and Clips. Yes No <code>Storyteller.clipShares</code> Share counts for the Clips loaded on the page, including the user's own shares. Yes No <code>Storyteller.customInstanceHost</code> A custom Storyteller API host, when your integration sets one. No Yes <code>Storyteller.environment</code> The Storyteller API environment that the SDK uses. No No <code>Storyteller.forceShowShareButton</code> A Storyteller testing flag. The SDK sets it to <code>false</code> when the user changes. No No <code>Storyteller.hasShownInstructions</code> Whether the user has seen the instructions screen. Yes No <code>Storyteller.likes</code> The Clips the user liked. Stored only when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <code>Storyteller.pollAnswers</code> The user's Poll answers. Stored only when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <code>Storyteller.polls</code> Poll data for the Stories loaded on the page. No Yes <code>Storyteller.quizAnsweredCorrectlyMap</code> The user's Quiz scores, used to show their results. Yes Yes <code>Storyteller.quizzes</code> Quiz data for the Stories loaded on the page. No Yes <code>Storyteller.readPages</code> The Story Pages the user has read. Stored only when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <code>Storyteller.recentStoryPlaybackMode</code> The analytics <code>storyPlaybackMode</code> value for each recently opened Story. Yes No <code>Storyteller.settings</code> Your tenant settings for the API key. No Yes <code>Storyteller.triviaQuizAnswers</code> The user's Quiz answers. Stored only when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <code>Storyteller.user</code> The hashed user ID. The SDK creates an anonymous ID or hashes the <code>externalId</code> passed to <code>initialize</code>. Not stored when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <code>Storyteller.userAttributesStorage</code> The user attributes set with <code>setUserAttribute</code> and <code>setLocale</code>. Yes No <code>Storyteller.viewedClips</code> The Clips the user has viewed. Stored only when <code>enableRemoteViewingStore</code> is <code>false</code>. Yes No <p>Versions before 10.11.0 stored an unhashed user ID in <code>Storyteller.userId</code>. The SDK removes that item when it saves <code>Storyteller.user</code>.</p>"},{"location":"PrivacyAndTracking/#keys-renamed-in-110","title":"Keys renamed in 11.0","text":"<p>Version 11.0 renamed the items that hold viewing history. The SDK doesn't read the old items and doesn't remove them, even when <code>enableFunctionalCookies</code> is <code>false</code>. If your consent manager or cleanup script lists Storyteller items, add the new names. Remove the old items yourself if your consent policy requires it.</p> Version 10.13 item Version 11.0 item <code>Storyteller.clipLikes</code> <code>Storyteller.likes</code> <code>Storyteller.clipsViewed</code> <code>Storyteller.viewedClips</code> <code>Storyteller.pollAnswerMap</code> <code>Storyteller.pollAnswers</code> <code>Storyteller.quizAnswerMap</code> <code>Storyteller.triviaQuizAnswers</code> <code>Storyteller.storiesReadMap</code> <code>Storyteller.readPages</code> <p>See Local storage keys changed in the migration guide.</p>"},{"location":"PrivacyAndTracking/#user-personalization","title":"User personalization","text":"<p>By default, the SDK includes user attributes and the user ID in requests to Storyteller, so Storyteller can personalize the content it returns. Set <code>enablePersonalization</code> to <code>false</code> to turn off personalization. The SDK then removes the stored user attributes and doesn't store new ones. Viewing history still loads, because it follows the remote viewing store option.</p> <p>The Storyteller Web Showcase's <code>persistAndApplyAttributeValues</code> helper shows how to store user attributes and apply them before they affect personalization.</p> <p>Warning</p> <p>Personalization is always off when <code>enableFunctionalCookies</code> is <code>false</code>, because the SDK doesn't store user IDs.</p>"},{"location":"PrivacyAndTracking/#remote-viewing-store","title":"Remote viewing store","text":"<p>When <code>enableRemoteViewingStore</code> is <code>true</code> (the default), Storyteller keeps the user's viewing history: read Pages, Clip likes and views, and Poll and Quiz answers. <code>initialize</code> loads the history for the current user ID, and the SDK doesn't keep it in local storage. See Identify and personalize users.</p> <p>Loading the history also needs <code>enableFunctionalCookies</code>. If it is <code>false</code> while this option is <code>true</code>, the SDK doesn't load the history, and it keeps the user's viewing state in memory only until the page reloads. The history request does not depend on <code>enablePersonalization</code>, and it never includes user attributes.</p> <p>When <code>enableRemoteViewingStore</code> is <code>false</code>, the SDK never stores user IDs or sends them to Storyteller, and it keeps all viewing activity in local storage on the device. This privacy-enhanced mode is designed to address Video Privacy Protection Act (VPPA) compliance concerns.</p>"},{"location":"PrivacyAndTracking/#storyteller-tracking","title":"Storyteller tracking","text":"<p>By default, the SDK records analytics events on Storyteller's servers. Set <code>enableStorytellerTracking</code> to <code>false</code> to turn off Storyteller analytics. The SDK still sends a few events that it needs to work, but Storyteller doesn't store them: <code>openedPage</code>, <code>votedPoll</code>, <code>triviaQuizQuestionAnswered</code>, <code>openedClip</code>, <code>likedClip</code>, and <code>unlikedClip</code>. The SDK doesn't send one of these events when you disable the matching functional feature, for example <code>votedPoll</code> when <code>pollVotes</code> is disabled.</p> <p>When Storyteller analytics are on, <code>initialize</code> also sends an <code>sdkInitialized</code> event. It includes the page origin and path, the browser viewport size, device and operating system details, and the tracking options.</p> <p>Warning</p> <p>Storyteller tracking is always off when <code>enableFunctionalCookies</code> is <code>false</code>. The SDK still sends the events listed above, without a user ID.</p>"},{"location":"PrivacyAndTracking/#user-activity-tracking","title":"User Activity tracking","text":"<p>Set <code>enableUserActivityTracking</code> to <code>false</code> to stop calls to the <code>onUserActivityOccurred</code> callback. Your site uses this callback to record Storyteller events in its own analytics. See Integrate analytics.</p> <p>A view's optional <code>context</code> value returns through this client callback when user activity tracking is enabled. The SDK excludes it from Storyteller analytics API requests. Your application owns the value and any transfer to another analytics provider. Keep credentials and personal data out of this field.</p>"},{"location":"Quickstart/","title":"Show your first Story row","text":"<p>This quickstart shows one row of published Stories on a web page. You add a container, initialize the SDK, create the row, and check that Stories loaded. Before you start lists what you need.</p> <p> </p>"},{"location":"Quickstart/#install-the-sdk","title":"Install the SDK","text":"<p>Install the SDK with one of these guides, then return to this page:</p> <ul> <li>Install with a script tag: load   <code>storyteller.min.js</code> from the Storyteller CDN</li> <li>Install from npm: use an ES module <code>import</code> or a   CommonJS <code>require</code></li> <li>Use React or Next.js: initialize the SDK   once and create the view in an effect</li> </ul> <p>The steps below use the SDK as <code>Storyteller</code>. The samples use <code>await</code>, which works only in JavaScript modules and inside <code>async</code> functions. In a classic <code>&lt;script&gt;</code>, wrap the code in an <code>async</code> function, as shown in Handle initialization errors.</p>"},{"location":"Quickstart/#add-a-container","title":"Add a container","text":"<pre><code>&lt;div id=\"storyteller-stories-row\" style=\"height: 200px\"&gt;&lt;/div&gt;\n</code></pre> <p>The row sizes its tiles to the container's height, so set a height on the container. If the container has no height, the SDK uses a default tile height (160 px for square tiles, 120 px or 140 px for round tiles). When logging is enabled, it also logs a warning.</p> <p>Warning</p> <p>The container ID must be unique on the page and follow best practices for HTML IDs. Use only ASCII letters, numbers, dashes (<code>-</code>), and underscores (<code>_</code>).</p> <p></p>"},{"location":"Quickstart/#initialize-storyteller","title":"Initialize Storyteller","text":"<p>Call <code>initialize</code> with your API key, and wait for it to resolve before you create a view:</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key');\n</code></pre> <p>Replace <code>demo-api-key</code> with your API key. If the user is signed in, pass your user ID as <code>externalId</code>. With the default privacy options, the user's viewing history then follows them across browsers and devices:</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key', {\n  externalId: 'your-user-id',\n});\n</code></pre> <p>Identify and personalize users explains user IDs and how to change the user.</p> <p></p>"},{"location":"Quickstart/#create-the-row","title":"Create the row","text":"<pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView(\n  'storyteller-stories-row'\n);\n</code></pre> <p>The constructor takes the container ID and an optional list of Category IDs: <code>StorytellerStoriesRowView(containerId: string, categories?: string[])</code>. To show Stories from specific Categories only, pass their IDs:</p> <pre><code>const filteredStoryRow = new Storyteller.StorytellerStoriesRowView(\n  'storyteller-stories-row',\n  ['category-id']\n);\n</code></pre> <p>Choose a view lists the grid and Clips views. The Storyteller Web Showcase creates a row with the same <code>StorytellerStoriesRowView</code> constructor.</p> <p></p>"},{"location":"Quickstart/#handle-initialization-errors","title":"Handle initialization errors","text":"<p><code>initialize</code> returns a promise that rejects when the SDK can't start. Catch the error and show a fallback in your page. Without top-level <code>await</code>, use an <code>async</code> function:</p> <pre><code>async function initializeStoryteller() {\n  try {\n    await Storyteller.sharedInstance.initialize('demo-api-key');\n    // Create Storyteller views here.\n  } catch (error) {\n    console.error('Storyteller could not start.', error);\n  }\n}\n\ninitializeStoryteller();\n</code></pre> <p>You can also handle the promise directly:</p> <pre><code>Storyteller.sharedInstance\n  .initialize('demo-api-key')\n  .then(() =&gt; {\n    // Create Storyteller views here.\n  })\n  .catch((error) =&gt; {\n    console.error('Storyteller could not start.', error);\n  });\n</code></pre> <p>The promise rejects with an <code>Error</code> whose <code>message</code> starts with the error type, for example <code>InvalidApiKeyError - The API Key provided was invalid</code>. The SDK doesn't export these error classes, and <code>error.name</code> is always <code>\"Error\"</code>, so check the start of the message, for example <code>error.message.startsWith('InvalidApiKeyError')</code>:</p> <ul> <li><code>InvalidApiKeyError</code>: Storyteller rejected the API key (HTTP 401 or 404)</li> <li><code>NetworkTimeoutError</code>: a request timed out</li> <li><code>NetworkError</code>: a request failed, or returned an empty or malformed response</li> </ul> <p>These errors come from the settings request. With the default privacy options, <code>initialize</code> also requests the user's viewing history (<code>GET /api/UserActivity/{userId}</code>) and waits for it. If that request fails, <code>initialize</code> rejects with one of the same errors.</p> <p>If you call <code>initialize</code> without an API key, the promise rejects with a text message instead of an <code>Error</code>.</p> <p>Earlier guides also listed <code>InitializationError</code> and <code>JsonParseError</code>. The SDK reports those cases as <code>NetworkError</code>.</p>"},{"location":"Quickstart/#check-the-result","title":"Check the result","text":"<p>A horizontal row of Story tiles appears. Selecting a tile opens the Story player.</p> <p>To see whether the row loaded, set a delegate on the row with an <code>onDataLoadComplete</code> callback:</p> <pre><code>storyRow.delegate = {\n  onDataLoadComplete: (success, error, dataCount) =&gt; {\n    if (success) {\n      console.log(`Loaded ${dataCount} Stories.`);\n    } else {\n      console.error('Stories could not load.', error?.message);\n    }\n  },\n};\n</code></pre> <p><code>success</code> is <code>false</code> when the request fails or returns no Stories. When no Stories are returned, <code>error.message</code> starts with <code>EmptyResponseError</code>.</p> What you see What to check <code>initialize</code> rejects Check the API key and the error message. See Handle initialization errors. <code>success</code> is <code>false</code> and <code>error.message</code> starts with <code>EmptyResponseError</code> The request worked but returned no Stories. Check the Category IDs, and check that the Stories are published in the same tenant as the API key. <code>success</code> is <code>false</code> with another error Find the failed request in the browser Network panel, and check its HTTP status. <code>success</code> is <code>true</code>, but no tiles show Check the container's height and width, and check for page CSS that hides it. <p>Troubleshoot an integration covers more problems.</p> <p> </p>"},{"location":"Quickstart/#next-steps","title":"Next steps","text":"<ul> <li>Add a Story or Clips row</li> <li>Choose a view</li> <li>Customize themes</li> <li>Handle delegates and callbacks</li> </ul>"},{"location":"StorytellerDelegate/","title":"Handle global callbacks","text":"<p>Set <code>Storyteller.sharedInstance.delegate</code> to handle events from every Storyteller view and player: analytics events, share taps, ad requests, and in-app action links. The delegate is an object typed <code>IStorytellerDelegate</code>. For loading and dismissal events from one row, grid, or Clips player, see Handle view callbacks.</p>"},{"location":"StorytellerDelegate/#how-to-use","title":"Set the delegate","text":"<p>Assign an object with the callbacks you need to <code>Storyteller.sharedInstance.delegate</code>. Set it before you call <code>initialize</code>, so that it receives the <code>sdkInitialized</code> event.</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    console.log(type, data.context);\n  },\n};\n</code></pre> <p>Warning</p> <p>Assigning <code>delegate</code> replaces all four global callbacks. A callback you leave out of the new object stops being called, even if an earlier assignment set it. Define every callback in one object, or spread the current delegate into the new one.</p> <pre><code>const getAdConfig = (adRequestInfo) =&gt; {\n  // Return { slot, customTargeting, publisherProvidedId }, or null for no ad.\n  // See Integrate ads.\n  return null;\n};\n\nStoryteller.sharedInstance.delegate = {\n  ...Storyteller.sharedInstance.delegate,\n  getAdConfig,\n};\n</code></pre>"},{"location":"StorytellerDelegate/#methods","title":"Callbacks","text":"<p>All callbacks are optional.</p>"},{"location":"StorytellerDelegate/#onuseractivityoccurred","title":"onUserActivityOccurred","text":"<pre><code>onUserActivityOccurred?: (type: ActivityType, data: UserActivityData) =&gt; void;\n</code></pre> <p>Called when an analytics event occurs in a Story or Clips player. A view with a <code>context</code> returns that value in <code>data.context</code>. See Analytics context for the supported views, inheritance rules, and data boundary. The SDK calls this callback only while <code>enableUserActivityTracking</code> is on, and sends ad events only while <code>enableAdTracking</code> is also on. See Integrate analytics for the event types.</p> <p>The Storyteller Web Showcase has an <code>onUserActivityOccurred</code> handler.</p>"},{"location":"StorytellerDelegate/#onsharebuttontapped","title":"onShareButtonTapped","text":"<pre><code>onShareButtonTapped?: (text: string, title: string, url: string) =&gt; Promise&lt;void&gt;;\n</code></pre> <p>Called when the user taps the share button in a Story or a Clip. Use it to replace the default share behavior. The SDK passes the text, title, and URL it would otherwise share, and pauses the Story or Clip. When your promise resolves, the SDK records a <code>shareSuccess</code> event. When the promise resolves or rejects, the Story or Clip plays again.</p> <p>If you don't implement this callback, the SDK opens the browser's share sheet with <code>navigator.share</code>. The share button appears only in browsers that support <code>navigator.share</code>, even when you implement this callback. Story Pages that share their media file download it instead and don't call this callback.</p> <p>The Storyteller Web Showcase shows an <code>onShareButtonTapped</code> override.</p>"},{"location":"StorytellerDelegate/#getadconfig","title":"getAdConfig","text":"<pre><code>getAdConfig?: (adRequestInfo: StorytellerAdRequestInfo) =&gt; AdConfig | null;\n</code></pre> <p>Called when a Story or Clips player needs an ad and your tenant uses Google Ad Manager ads. Return an object with these fields, or <code>null</code> for no ad:</p> <ul> <li><code>slot</code>: the ad unit path to request</li> <li><code>customTargeting</code> (optional): key-value pairs for ad targeting</li> <li><code>publisherProvidedId</code> (optional): your publisher provided ID</li> </ul> <p>Story ad requests include <code>story</code>. Clips ad requests include <code>clip</code>, <code>nextClip</code>, and <code>collection</code>, and have no <code>story</code> field. The SDK doesn't export the <code>AdConfig</code> type. See Integrate ads for the full request and response details.</p> <p>The Storyteller Web Showcase's <code>buildAdConfig</code> shows how to return slots and custom targeting values.</p>"},{"location":"StorytellerDelegate/#usernavigatedtoapp","title":"userNavigatedToApp","text":"<pre><code>userNavigatedToApp?: (url: string) =&gt; void;\n</code></pre> <p>Called when a user taps an action button in a Story or Clip that links into your app (an <code>inApp</code> action). Route the user to <code>url</code> in your app. If you don't implement this callback, <code>inApp</code> actions open like regular URLs.</p>"},{"location":"StorytellerDelegate/#delegate-interface","title":"Delegate interface","text":"<pre><code>interface IStorytellerDelegate {\n  onUserActivityOccurred?: (type: ActivityType, data: UserActivityData) =&gt; void;\n\n  onShareButtonTapped?: (\n    text: string,\n    title: string,\n    url: string\n  ) =&gt; Promise&lt;void&gt;;\n\n  getAdConfig?: (adRequestInfo: StorytellerAdRequestInfo) =&gt; AdConfig | null;\n\n  userNavigatedToApp?: (url: string) =&gt; void;\n}\n</code></pre> <p>For a full implementation that wires every callback, see the Storyteller Web Showcase's <code>attachStorytellerDelegate</code>.</p>"},{"location":"StorytellerEmbeddedClipsPlayerView/","title":"Add a Clips player to a page","text":"<p>Use a Clips player view to play Clips in an element on your page, instead of opening the Clips player from a row or grid. The Web SDK has two Clips player views. Both render into your container, fill it, and accept the same content sources, configuration, and delegate.</p>"},{"location":"StorytellerEmbeddedClipsPlayerView/#choose-a-clips-player-view","title":"Choose a Clips player view","text":"View Use it for Behavior <code>StorytellerEmbeddedClipsPlayerView</code> Clips inside other page content, such as a live blog or match center Shows one Clip at a time. The rest of the page keeps scrolling. <code>Storyteller.sharedInstance.dismissPlayer</code> doesn't close it. <code>StorytellerClipsPlayerView</code> An area of the page set aside for Clips Uses the full Clips player layout, which can show neighboring Clips on wide screens. Locks page scrolling while it's shown. <code>dismissPlayer</code> dismisses it. <p>The rest of this page uses <code>StorytellerEmbeddedClipsPlayerView</code>. The same steps apply to <code>StorytellerClipsPlayerView</code>.</p>"},{"location":"StorytellerEmbeddedClipsPlayerView/#initialization","title":"Initialization","text":"<p><code>StorytellerEmbeddedClipsPlayerView</code> accepts the same content sources as <code>StorytellerClipsPlayerView</code>: a collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code>.</p> <pre><code>const embeddedCollectionPlayer =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    'clip-collection-id'\n  );\n\nconst embeddedSingleClipPlayer =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { clipId: 'clip-id' }\n  );\n\nconst embeddedSingleClipPlayerByExternalId =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { externalId: 'clip-external-id' }\n  );\n</code></pre> <p>Provide exactly one source. With a collection ID, the player keeps collection behavior: users can move between the collection's Clips when the collection supports it. With <code>{ clipId }</code> or <code>{ externalId }</code>, the player shows only that Clip. The constructor throws an <code>Error</code> if you pass no source or more than one.</p>"},{"location":"StorytellerEmbeddedClipsPlayerView/#sizing","title":"Sizing","text":"<p>Set the player's size with CSS on the container. The constructor has no <code>width</code> or <code>height</code> options.</p> <p>For portrait Clips, set the container width and use a <code>9 / 16</code> aspect ratio so the browser works out the height:</p> <pre><code>&lt;div\n  id=\"embedded-clips-player-id\"\n  style=\"width: 430px; max-width: 100%; aspect-ratio: 9 / 16;\"\n&gt;&lt;/div&gt;\n</code></pre> <pre><code>const embeddedSingleClipPlayer =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { externalId: 'clip-external-id' }\n  );\n</code></pre>"},{"location":"StorytellerEmbeddedClipsPlayerView/#configuration","title":"Configuration","text":"<p>The embedded Clips player uses the same configuration fields as <code>StorytellerClipsPlayerView</code>. See Configure views for every field. The TypeScript example assumes <code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';</code> and imports the <code>IStorytellerEmbeddedClipsPlayerConfiguration</code> type.</p> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst embeddedClipPlayer = new Storyteller.StorytellerEmbeddedClipsPlayerView(\n  'embedded-clips-player-id',\n  { externalId: 'clip-external-id' }\n);\nconst embeddedClipPlayerConfiguration: IStorytellerEmbeddedClipsPlayerConfiguration =\n  {\n    theme: customTheme,\n    uiStyle: Storyteller.UiStyle.dark,\n  };\n\nembeddedClipPlayer.configuration = embeddedClipPlayerConfiguration;\n</code></pre> <p>You can also change the source through <code>configuration</code>. Provide exactly one of <code>collection</code>, <code>clipId</code>, or <code>externalId</code>. An update with an invalid source logs an error and keeps the current source.</p> <pre><code>embeddedClipPlayer.configuration = {\n  externalId: 'new-clip-external-id',\n};\n</code></pre>"},{"location":"StorytellerEmbeddedClipsPlayerView/#back-button-delegate","title":"Handle the back button","text":"<p><code>StorytellerEmbeddedClipsPlayerView</code> uses the Clips player delegate (<code>IStorytellerClipsPlayerDelegate</code>) through the same <code>delegate</code> property as <code>StorytellerClipsPlayerView</code>. See Handle view callbacks for every callback.</p> <pre><code>const embeddedClipPlayer = new Storyteller.StorytellerEmbeddedClipsPlayerView(\n  'embedded-clips-player-id',\n  { externalId: 'clip-external-id' }\n);\n\nembeddedClipPlayer.topLevelBackButtonEnabled = true;\nembeddedClipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <p><code>onPlayerDismissed</code> means that the player was dismissed, so the back button doesn't call it. The button calls <code>onTopLevelBackTapped</code> if you define it; otherwise, it calls <code>window.history.back()</code>.</p> <p>When <code>topLevelBackButtonEnabled</code> is <code>false</code> or not set, the player doesn't show the back button and doesn't call <code>onTopLevelBackTapped</code> from it.</p>"},{"location":"StorytellerEmbeddedClipsPlayerView/#clips-player-view","title":"Use a Clips player for a dedicated area","text":"<p>Use <code>StorytellerClipsPlayerView</code> when an area of your page, such as a Clips section or a Clips page, is set aside for the player. It takes the same arguments, configuration, and delegate as <code>StorytellerEmbeddedClipsPlayerView</code>:</p> <pre><code>const clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  'clip-collection-id'\n);\n\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <p><code>StorytellerClipsPlayerView</code> differs from the embedded player in three ways:</p> <ul> <li>It uses the full Clips player layout, which can show neighboring Clips on wide screens.</li> <li>It locks page scrolling while it's shown.</li> <li><code>Storyteller.sharedInstance.dismissPlayer</code> dismisses it and calls its <code>onPlayerDismissed</code> callback.</li> </ul> <p>For its constructor and configuration, see Clips player initialization and Clips player configuration.</p>"},{"location":"StorytellerGridView/","title":"Add a Story or Clips grid","text":"<p>A grid shows Story or Clip tiles in columns. Use <code>StorytellerStoriesGridView</code> for Stories and <code>StorytellerClipsGridView</code> for Clips. Set the number of columns with the <code>lists.grid.columns</code> theme property. To show a grid only when it has content, check <code>getStoriesCount</code> or <code>getClipsCount</code> first.</p>"},{"location":"StorytellerGridView/#initialization","title":"Initialization","text":"<p>Create the grid with the ID of an existing element on your page. Grids take the same arguments as the other views in Configure views:</p>"},{"location":"StorytellerGridView/#stories-initialization","title":"Stories initialization","text":"<pre><code>const storyGrid = new Storyteller.StorytellerStoriesGridView('stories-grid-id'); // All Categories\nconst storyGridWithCategories = new Storyteller.StorytellerStoriesGridView(\n  'stories-grid-id',\n  ['category-1', 'category-2']\n);\n</code></pre>"},{"location":"StorytellerGridView/#clips-initialization","title":"Clips initialization","text":"<pre><code>const clipsGrid = new Storyteller.StorytellerClipsGridView(\n  'clips-grid-id',\n  'clip-collection-id'\n);\n</code></pre>"},{"location":"StorytellerGridView/#configuration","title":"Configuration","text":"<p>Grids accept every setting in Configure views. Grids don't use <code>cellType</code>. TypeScript examples assume <code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';</code> and <code>import type { IListConfiguration } from '@getstoryteller/storyteller-sdk-javascript';</code>.</p>"},{"location":"StorytellerGridView/#stories-configuration","title":"Stories configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyGrid = new Storyteller.StorytellerStoriesGridView('stories-grid-id');\nstoryGrid.configuration = {\n  categories: ['category1', 'category2', 'category3'], // Stories only\n  displayLimit: 10,\n  preload: true, // Stories only\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyGrid = new Storyteller.StorytellerStoriesGridView('stories-grid-id');\nconst storyGridConfiguration: IListConfiguration&lt;'StorytellerStoriesGridView'&gt; =\n  {\n    categories: ['category1', 'category2', 'category3'], // Stories only\n    displayLimit: 10,\n    preload: true, // Stories only\n    theme: customTheme,\n    uiStyle: Storyteller.UiStyle.dark,\n  };\nstoryGrid.configuration = storyGridConfiguration;\n</code></pre> <p>For a live example, review the Storyteller Web Showcase's <code>StorytellerStoriesGridView</code>, which sets <code>basename</code>, <code>displayLimit</code>, and custom themes.</p>"},{"location":"StorytellerGridView/#clips-configuration","title":"Clips configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsGrid = new Storyteller.StorytellerClipsGridView(\n  'clips-grid-id',\n  'collection-id'\n);\nclipsGrid.configuration = {\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsGrid = new Storyteller.StorytellerClipsGridView(\n  'clips-grid-id',\n  'collection-id'\n);\nconst clipsGridConfiguration: IListConfiguration&lt;'StorytellerClipsGridView'&gt; = {\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipsGrid.configuration = clipsGridConfiguration;\n</code></pre> <p>For Clips, the Storyteller Web Showcase's <code>StorytellerClipsGridView</code> sets the collection ID and display limit with the same <code>configuration</code> object.</p>"},{"location":"StorytellerListView/","title":"Configure views","text":"<p>This page covers the settings and methods shared by every Storyteller view: Story and Clips rows and grids, and the two Clips player views. For the settings that only rows or only grids use, see Add a Story or Clips row and Add a Story or Clips grid.</p> <p>Note</p> <p>Most examples use <code>StorytellerStoriesRowView</code>. The same settings apply to <code>StorytellerStoriesGridView</code>, <code>StorytellerClipsRowView</code>, and <code>StorytellerClipsGridView</code>. Where <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code> works differently, the section says so.</p>"},{"location":"StorytellerListView/#initialization","title":"Initialization","text":"<p>Create each view with the ID of an existing element on your page, followed by its content source.</p>"},{"location":"StorytellerListView/#stories-initialization","title":"Stories initialization","text":"<pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id'); // All Categories\nconst storyRowWithCategories = new Storyteller.StorytellerStoriesRowView(\n  'stories-row-id',\n  ['category-1', 'category-2']\n);\n</code></pre>"},{"location":"StorytellerListView/#clips-initialization","title":"Clips initialization","text":"<pre><code>const clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'clip-collection-id'\n);\n</code></pre>"},{"location":"StorytellerListView/#clips-player-initialization","title":"Clips player initialization","text":"<p><code>StorytellerClipsPlayerView</code> shows the Clips player in your container instead of opening it from a row or grid. Pass a collection ID to play the collection, or <code>{ clipId }</code> or <code>{ externalId }</code> to play one Clip. For a player inside other page content, such as a live blog, use <code>StorytellerEmbeddedClipsPlayerView</code>. Add a Clips player to a page compares the two views.</p> <pre><code>const collectionPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  'clip-collection-id'\n);\n\nconst singleClipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { clipId: 'clip-id' }\n);\n\nconst singleClipPlayerByExternalId = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\n</code></pre> <p>The constructor throws an <code>Error</code> if you pass no source or more than one source.</p> <p>The Storyteller Web Showcase picks a Stories row or grid for each feed module from its layout with <code>isGridLikeLayout</code>.</p>"},{"location":"StorytellerListView/#story-ordering","title":"Story ordering","text":"<p>Rows and grids can order Stories by what the user has already read. Storyteller sets the ordering for your content in the Stories API response; you don't set it in code. With the default read ordering, unread Stories come before read Stories. With started-aware ordering, Stories appear in three groups: not opened, started, and finished. Pinned Stories stay first, and Live Stories stay ahead of the other Stories. Within each group, Stories keep the order set in the Storyteller CMS.</p>"},{"location":"StorytellerListView/#clips-paging","title":"Clips paging","text":"<p>Clips rows, grids, and players that show a collection load more Clips when the user reaches the last loaded Clip, including inside a Clip Category. The SDK skips Clips it has already shown and stops when the collection has no more Clips. You don't need to change your code.</p> <ul> <li><code>reloadData</code> loads the first page again.</li> <li>The view's <code>onDataLoadComplete</code>   callback reports the first page only. Later pages load without delegate   callbacks.</li> <li>A Clips player that shows one Clip, created with <code>{ clipId }</code> or   <code>{ externalId }</code>, doesn't load more Clips.</li> </ul>"},{"location":"StorytellerListView/#clip-details","title":"Clip details","text":"<p>The Clips player shows a Clip's long description when the Clip has one. The title, description, and Categories show a short preview, and one control expands or collapses them. Long details scroll inside the player. A Clip without a description shows its title and Categories. To hide the title, see the Clips player theme settings.</p>"},{"location":"StorytellerListView/#rtl-support","title":"Right-to-left (RTL) pages","text":"<p>The Web SDK supports right-to-left host pages for Stories rows, Clips rows, and the Story player.</p>"},{"location":"StorytellerListView/#host-page-setup","title":"Host page setup","text":"<p>Set <code>dir=\"rtl\"</code> on the page or on the closest container that wraps the SDK view:</p> <pre><code>&lt;section dir=\"rtl\"&gt;\n  &lt;div id=\"stories-row-id\"&gt;&lt;/div&gt;\n&lt;/section&gt;\n</code></pre> <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\n</code></pre> <p>The SDK reads the text direction from the view's container and its ancestors, so one page can mix directions. For example, a left-to-right page can show one Storyteller row inside a right-to-left section.</p>"},{"location":"StorytellerListView/#supported-surfaces","title":"Supported surfaces","text":"<p>RTL support applies to:</p> <ul> <li><code>StorytellerStoriesRowView</code></li> <li><code>StorytellerClipsRowView</code></li> <li>Story players opened from Stories rows and grids</li> </ul> <p>In a right-to-left row, the scroll controls, edge fades, and disabled states follow the right-to-left scroll direction.</p> <p>When a Story opens from an RTL page, the Story player uses right-to-left text and controls.</p>"},{"location":"StorytellerListView/#configuration","title":"Configuration","text":"<p>Set a view's options by assigning an object to its <code>configuration</code> property. Assigning a partial object updates only the fields it contains. In TypeScript, type the object with <code>IListConfiguration&lt;'StorytellerStoriesRowView'&gt;</code> (use the view's class name), <code>IStorytellerClipsPlayerConfiguration</code>, or <code>IStorytellerEmbeddedClipsPlayerConfiguration</code>.</p> <p>TypeScript examples</p> <p>The TypeScript examples in these guides assume <code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';</code> and import the configuration types they use, for example <code>import type { IListConfiguration } from '@getstoryteller/storyteller-sdk-javascript';</code>.</p>"},{"location":"StorytellerListView/#stories-configuration","title":"Stories configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nstoryRow.configuration = {\n  basename: 'top-stories', // Needed if there are multiple lists on the same page\n  categories: ['category1', 'category2', 'category3'], // Stories only\n  cellType: Storyteller.CellType.round, // StorytellerStoriesRowView only\n  context: {\n    source: 'homepage-stories',\n    campaign: 'summer-league'\n  },\n  displayLimit: 10,\n  preload: true, // Stories only\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nconst storyRowConfiguration: IListConfiguration&lt;'StorytellerStoriesRowView'&gt; = {\n  basename: 'top-stories', // Needed if there are multiple lists on the same page\n  categories: ['category1', 'category2', 'category3'], // Stories only\n  cellType: Storyteller.CellType.round, // StorytellerStoriesRowView only\n  context: {\n    source: 'homepage-stories',\n    campaign: 'summer-league'\n  },\n  displayLimit: 10,\n  preload: true, // Stories only\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nstoryRow.configuration = storyRowConfiguration;\n</code></pre>"},{"location":"StorytellerListView/#clips-configuration","title":"Clips configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'collection-id'\n);\nclipsRow.configuration = {\n  basename: 'top-clips', // Needed if there are multiple lists with the same collection on the same page\n  context: {\n    source: 'homepage-clips',\n    campaign: 'summer-league'\n  },\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'collection-id'\n);\nconst clipsRowConfiguration: IListConfiguration&lt;'StorytellerClipsRowView'&gt; = {\n  basename: 'top-clips', // Needed if there are multiple lists with the same collection on the same page\n  context: {\n    source: 'homepage-clips',\n    campaign: 'summer-league'\n  },\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipsRow.configuration = clipsRowConfiguration;\n</code></pre>"},{"location":"StorytellerListView/#clips-player-configuration","title":"Clips player configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\nclipPlayer.configuration = {\n  basename: 'highlight-player',\n  context: {\n    source: 'homepage-highlight',\n    campaign: 'google-highlights'\n  },\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\nconst clipPlayerConfiguration: IStorytellerClipsPlayerConfiguration = {\n  basename: 'highlight-player',\n  context: {\n    source: 'homepage-highlight',\n    campaign: 'google-highlights'\n  },\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipPlayer.configuration = clipPlayerConfiguration;\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre>"},{"location":"StorytellerListView/#embedded-clips-player-configuration","title":"Embedded Clips player configuration","text":"<p><code>StorytellerEmbeddedClipsPlayerView</code> uses the same configuration fields as <code>StorytellerClipsPlayerView</code>:</p> JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst embeddedClipPlayer =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { externalId: 'clip-external-id' }\n  );\nembeddedClipPlayer.configuration = {\n  basename: 'live-blog-highlight-player',\n  context: {\n    location: 'live-blog',\n    module: 'highlight-player',\n  },\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nembeddedClipPlayer.topLevelBackButtonEnabled = true;\nembeddedClipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst embeddedClipPlayer =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { externalId: 'clip-external-id' }\n  );\nconst embeddedClipPlayerConfiguration: IStorytellerEmbeddedClipsPlayerConfiguration = {\n  basename: 'live-blog-highlight-player',\n  context: {\n    location: 'live-blog',\n    module: 'highlight-player',\n  },\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nembeddedClipPlayer.configuration = embeddedClipPlayerConfiguration;\nembeddedClipPlayer.topLevelBackButtonEnabled = true;\nembeddedClipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <p>Learn more</p> <p>See Add a Story or Clips row and Add a Story or Clips grid for the settings specific to rows and grids.</p>"},{"location":"StorytellerListView/#basename","title":"basename","text":"<p>Each Stories or Clips view has a <code>basename</code>, which is the first segment of the player's hash URL. For example:</p> <pre><code>https://www.getstoryteller.com/#basename/story-id\nhttps://www.getstoryteller.com/#basename/collection-id/clip-id\n</code></pre> <p>By default, the <code>basename</code> is <code>stories</code> for Stories views and <code>clips</code> for Clips views. To change it, set <code>basename</code> in <code>configuration</code>:</p> <pre><code>storyRow.configuration = {\n  basename: 'top-stories',\n};\n</code></pre> <p>If a page has only one Stories or Clips view, <code>basename</code> is optional. Opening a Story then goes to <code>#stories/story-id</code>, and opening a Clip goes to <code>#clips/collection-id/clip-id</code>.</p> <p>If a page has several views, the SDK derives each view's <code>basename</code> from its Categories or collection. If two views have the same Categories or collection, set a different <code>basename</code> on each so that every view has a unique <code>basename</code>. Views with different Categories don't need one, but you can set it to make the player URL easier to read.</p> <p>Note</p> <p>The SDK removes every character from a basename except ASCII letters, numbers, dashes (<code>-</code>), and underscores (<code>_</code>).</p>"},{"location":"StorytellerListView/#categories-stories-only","title":"categories (Stories only)","text":"<p>Set <code>categories</code> to show only Stories from those Categories. Without <code>categories</code>, the view shows the Stories in your Home list.</p> <p>To change the Categories of a Storyteller row, assign new ones in <code>configuration</code>:</p> <pre><code>storyRow.configuration = {\n  categories: ['new-category-id-1', 'new-category-id-2'],\n};\n</code></pre> <p>Copy Category IDs from the Storyteller CMS.</p> <p>Learn more</p> <p>See Categories for more information about managing Categories in the CMS.</p>"},{"location":"StorytellerListView/#collection-clips-only","title":"collection (Clips only)","text":"<p>A Clips view needs a collection ID when you create it:</p> <pre><code>const clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'clip-collection-id'\n);\n</code></pre> <p>To change the collection later, set <code>collection</code> in <code>configuration</code>:</p> <pre><code>clipsRow.configuration = {\n  collection: 'new-clip-collection-id',\n};\n</code></pre> <p>Copy the collection ID from the Storyteller CMS.</p> <p>Learn more</p> <p>See Creating Collections for more information about managing collections in the CMS.</p>"},{"location":"StorytellerListView/#clipid-externalid-clips-player-only","title":"clipId / externalId (Clips player only)","text":"<p>To play a single Clip in <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code>, pass an object with either <code>clipId</code> or <code>externalId</code>:</p> <pre><code>const clipPlayerById = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { clipId: 'clip-id' }\n);\n\nconst clipPlayerByExternalId = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\n\nconst embeddedClipPlayerByExternalId =\n  new Storyteller.StorytellerEmbeddedClipsPlayerView(\n    'embedded-clips-player-id',\n    { externalId: 'clip-external-id' }\n  );\n</code></pre> <p>To switch the player to a different Clip later, assign the new identifier in <code>configuration</code>:</p> <pre><code>clipPlayerById.configuration = {\n  clipId: 'new-clip-id',\n};\n\nclipPlayerByExternalId.configuration = {\n  externalId: 'new-clip-external-id',\n};\n</code></pre> <p>Set exactly one source on a Clips player: <code>collection</code>, <code>clipId</code>, or <code>externalId</code>. The constructor throws an <code>Error</code> if you pass no source or more than one. A later <code>configuration</code> update with an invalid source logs an error and keeps the current source.</p> <p>The <code>IStorytellerClipsPlayerConfiguration</code> and <code>IStorytellerEmbeddedClipsPlayerConfiguration</code> types include the same source fields.</p>"},{"location":"StorytellerListView/#toplevelbackbuttonenabled-clips-player-only","title":"topLevelBackButtonEnabled (Clips player only)","text":"<p>Set <code>topLevelBackButtonEnabled</code> on the player itself, not in <code>configuration</code>. It shows a back button at the top of a <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code>:</p> <pre><code>const clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\n\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <p>When the user taps the back button:</p> <ul> <li>If <code>clipPlayer.delegate.onTopLevelBackTapped</code> is defined, the SDK calls it and your code decides what happens next.</li> <li>If no callback is defined, the SDK calls <code>window.history.back()</code>.</li> </ul> <p><code>topLevelBackButtonEnabled</code> defaults to <code>false</code>, which hides the button. While the button is hidden, the SDK doesn't call <code>onTopLevelBackTapped</code>.</p>"},{"location":"StorytellerListView/#context","title":"context","text":"<p>Use <code>context</code> to identify the placement that produced an analytics event. The SDK returns its value in <code>UserActivityData.context</code> for each <code>onUserActivityOccurred</code> callback from the view.</p> <pre><code>clipsRow.configuration = {\n  context: {\n    location: 'home',\n    module: 'featured-clips',\n    sortOrder: 20,\n  },\n};\n</code></pre> <p>The field accepts any value. An <code>undefined</code> value omits <code>context</code> from the callback. Explicit values such as <code>null</code>, <code>false</code>, <code>0</code>, and an empty string stay in the callback. Reassign <code>configuration</code> to replace the value while the view is on the page.</p> <p>When a user opens related Story or Clip content through an SDK action, the related player keeps the source view's context. If two matching placements share a player, events use the context from the placement that the user chose. The configured value returns after the player is dismissed.</p> <p>The SDK adds <code>context</code> to the browser callback only. It doesn't add the field to Storyteller analytics API requests. The callback runs only while <code>enableUserActivityTracking</code> is on. Don't put credentials or personal data in <code>context</code>. See Analytics for the supported views, deep-link behavior, tracking controls, and data handling guidance.</p>"},{"location":"StorytellerListView/#displaylimit","title":"displayLimit","text":"<p><code>displayLimit</code> is the maximum number of tiles the view shows. It's optional.</p>"},{"location":"StorytellerListView/#preload","title":"preload","text":"<p>Each Stories row or grid starts a low-priority download of the AMP player script before the user opens a Story. Set <code>preload</code> to <code>true</code> to also prepare the Story player in advance. The first Story then opens sooner if that work finishes in time, but users who never open a Story download more code. <code>preload</code> defaults to <code>false</code>. Keep the default when the first page load matters most.</p>"},{"location":"StorytellerListView/#theme","title":"theme","text":"<p>Set <code>theme</code> to a <code>UiTheme</code> to style one view. It overrides the global theme (<code>Storyteller.sharedInstance.theme</code>) for that view only: the properties you set replace the global values, and the rest come from the global theme. A theme set in <code>configuration</code> stays in place when <code>initialize</code> runs again. See Customize themes.</p> <pre><code>const customTheme = new Storyteller.UiTheme({\n  light: {\n    lists: {\n      row: {\n        startInset: 0,\n        endInset: 0,\n      },\n    },\n  },\n});\n\nstoryRow.configuration = {\n  theme: customTheme,\n};\n</code></pre>"},{"location":"StorytellerListView/#uistyle","title":"uiStyle","text":"<p><code>uiStyle</code> sets whether the view uses the light theme, the dark theme, or follows the system setting. It takes a <code>Storyteller.UiStyle</code> value. JavaScript can also pass the strings <code>'auto'</code>, <code>'light'</code>, and <code>'dark'</code>.</p> <ul> <li><code>Storyteller.UiStyle.auto</code> (default): the view follows the system light or dark mode</li> <li><code>Storyteller.UiStyle.light</code>: the view always uses the light theme</li> <li><code>Storyteller.UiStyle.dark</code>: the view always uses the dark theme</li> </ul> <p>You can also set <code>uiStyle</code> on the container <code>div</code> with the <code>data-ui-style</code> attribute:</p> <pre><code>&lt;div id=\"storyteller-row\" data-ui-style=\"dark\"&gt;&lt;/div&gt;\n</code></pre>"},{"location":"StorytellerListView/#methods","title":"Methods","text":""},{"location":"StorytellerListView/#reloaddata","title":"reloadData","text":"<pre><code>reloadData(): Promise&lt;void&gt;\n</code></pre> <p><code>reloadData</code> loads the view's Stories or Clips from the API again. When the request finishes, the view updates its tiles, starts prefetching content, and updates the read status of its Stories or Clips. The view calls <code>onDataLoadStarted</code> and then <code>onDataLoadComplete</code> on its delegate, with the result of the request. Clips views load the first page again. The promise resolves when loading finishes.</p> <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nstoryRow.reloadData();\n</code></pre>"},{"location":"StorytellerListView/#destroy","title":"destroy","text":"<pre><code>destroy(): void\n</code></pre> <p>Call <code>destroy</code> before you remove or replace the view's container, for example when a single-page application changes route. The view removes what it rendered, removes its player container when no other view uses it, stops loading content and calling its delegate, and stops following theme changes. Calling <code>destroy</code> again does nothing. To show content in the same element again, create a new view. <code>destroy</code> is available on every view from version 11.0.0.</p> <pre><code>storyRow.destroy();\n</code></pre> <p>For React and Next.js, see Use React or Next.js.</p>"},{"location":"StorytellerListView/#openstory-openstorybyexternalid-openpage-opencollection-openclipbyexternalid","title":"openStory, openStoryByExternalId, openPage, openCollection, openClipByExternalId","text":"<p>These methods, and <code>openCategory</code>, are on <code>Storyteller.sharedInstance</code>, not on views.</p> <p>Learn more</p> <p>See Open a player programmatically for examples, and Use additional SDK methods for the full signatures.</p>"},{"location":"StorytellerListViewDelegate/","title":"Handle view callbacks","text":"<p>Each view has its own <code>delegate</code> for events from that view: loading its content and closing its player. <code>StorytellerStoriesRowView</code>, <code>StorytellerStoriesGridView</code>, <code>StorytellerClipsRowView</code>, and <code>StorytellerClipsGridView</code> use the list view delegate, typed <code>IListViewDelegate</code>. For events from every player, such as analytics, see Handle global callbacks.</p> <p><code>StorytellerClipsPlayerView</code> and <code>StorytellerEmbeddedClipsPlayerView</code> use the Clips player delegate, typed <code>IStorytellerClipsPlayerDelegate</code>, through the same <code>delegate</code> property. It adds a callback for the back button.</p>"},{"location":"StorytellerListViewDelegate/#set-a-view-delegate","title":"Set a view delegate","text":"<p>Set the <code>delegate</code> property on the view you want to observe. Assigning a new object replaces the view's previous delegate.</p> <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nstoryRow.delegate = {\n  // Add the callbacks you need, for example:\n  onDataLoadComplete: (success, error, dataCount) =&gt; {\n    if (!success) {\n      console.error('Stories could not load.', error);\n    }\n  },\n};\n</code></pre> <pre><code>const clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\nclipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <p>For the Clips player views' initialization, sizing, and back button, see Add a Clips player to a page.</p>"},{"location":"StorytellerListViewDelegate/#delegate-methods","title":"Delegate callbacks","text":"<p>All callbacks are optional.</p>"},{"location":"StorytellerListViewDelegate/#ondataloadstarted","title":"onDataLoadStarted","text":"<pre><code>onDataLoadStarted?: () =&gt; void;\n</code></pre> <p>Called when the view starts loading its Stories or Clips.</p>"},{"location":"StorytellerListViewDelegate/#ondataloadcomplete","title":"onDataLoadComplete","text":"<pre><code>onDataLoadComplete?: (success: boolean, error: Error | null, dataCount: number) =&gt; void;\n</code></pre> <p>Called when the view finishes loading its content:</p> <ul> <li><code>success</code>: <code>true</code> when content loaded. <code>false</code> when the request failed or returned no Stories or Clips.</li> <li><code>error</code>: an <code>Error</code> when <code>success</code> is <code>false</code>, otherwise <code>null</code>. The SDK doesn't export its error classes, so check <code>error.message</code>.</li> <li><code>dataCount</code>: the number of Stories loaded, or the number of Clips in the first page. Later Clips pages load without calling <code>onDataLoadStarted</code> or <code>onDataLoadComplete</code>. A Clips player that shows one Clip reports <code>1</code>.</li> </ul>"},{"location":"StorytellerListViewDelegate/#onplayerdismissed","title":"onPlayerDismissed","text":"<pre><code>onPlayerDismissed?: () =&gt; void;\n</code></pre> <p>Called when a Story or Clips player opened from this view is dismissed.</p>"},{"location":"StorytellerListViewDelegate/#clips-player-delegate","title":"Clips player delegate","text":"<p><code>IStorytellerClipsPlayerDelegate</code> has the same callbacks as <code>IListViewDelegate</code>, and adds <code>onTopLevelBackTapped</code>.</p>"},{"location":"StorytellerListViewDelegate/#ontoplevelbacktapped","title":"onTopLevelBackTapped","text":"<pre><code>onTopLevelBackTapped?: () =&gt; void;\n</code></pre> <p>Called when the user taps the back button at the top of a <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code> whose <code>topLevelBackButtonEnabled</code> is <code>true</code>.</p> <p>The back button doesn't call <code>onPlayerDismissed</code>. If you don't define <code>onTopLevelBackTapped</code>, the button calls <code>window.history.back()</code>. When <code>topLevelBackButtonEnabled</code> is <code>false</code> or not set, the button stays hidden and doesn't call <code>onTopLevelBackTapped</code>.</p>"},{"location":"StorytellerListViewDelegate/#delegate-interfaces","title":"Delegate interfaces","text":"<pre><code>interface IListViewDelegate {\n  onDataLoadStarted?: () =&gt; void;\n\n  onDataLoadComplete?: (\n    success: boolean,\n    error: Error | null,\n    dataCount: number\n  ) =&gt; void;\n\n  onPlayerDismissed?: () =&gt; void;\n}\n\ninterface IStorytellerClipsPlayerDelegate extends IListViewDelegate {\n  onTopLevelBackTapped?: () =&gt; void;\n}\n</code></pre> <p>The Storyteller Web Showcase hides a feed module when <code>onDataLoadComplete</code> reports a failure or no content, in <code>handleDataLoadComplete</code>.</p>"},{"location":"StorytellerRowView/","title":"Add a Story or Clips row","text":"<p>A row shows Story or Clip tiles in one horizontal line that users can scroll. Use <code>StorytellerStoriesRowView</code> for Stories and <code>StorytellerClipsRowView</code> for Clips. To show a row only when it has content, check <code>getStoriesCount</code> or <code>getClipsCount</code> first.</p>"},{"location":"StorytellerRowView/#initialization","title":"Initialization","text":"<p>Create the row with the ID of an existing element on your page. Rows take the same arguments as the other views in Configure views:</p>"},{"location":"StorytellerRowView/#stories-initialization","title":"Stories initialization","text":"<pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id'); // All Categories\nconst storyRowWithCategories = new Storyteller.StorytellerStoriesRowView(\n  'stories-row-id',\n  ['category-1', 'category-2']\n);\n</code></pre>"},{"location":"StorytellerRowView/#clips-initialization","title":"Clips initialization","text":"<pre><code>const clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'clip-collection-id'\n);\n</code></pre> <p>Note</p> <p>The row sizes its tiles to the height of its container. Set a height on the container, for example <code>&lt;div id=\"stories-row-id\" style=\"height: 200px\"&gt;&lt;/div&gt;</code>. If the container has no height, the SDK uses a default tile height (160 px for square tiles, and 120 px or 140 px for round tiles, depending on whether titles show). When logging is enabled, the SDK also logs a warning.</p>"},{"location":"StorytellerRowView/#configuration","title":"Configuration","text":"<p>Set a row's options with its <code>configuration</code> object. TypeScript examples assume <code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';</code> and <code>import type { IListConfiguration } from '@getstoryteller/storyteller-sdk-javascript';</code>.</p>"},{"location":"StorytellerRowView/#stories-configuration","title":"Stories configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nstoryRow.configuration = {\n  categories: ['category1', 'category2', 'category3'], // Stories only\n  cellType: Storyteller.CellType.round, // StorytellerStoriesRowView only\n  displayLimit: 10,\n  preload: true, // Stories only\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\nconst storyRowConfiguration: IListConfiguration&lt;'StorytellerStoriesRowView'&gt; = {\n  categories: ['category1', 'category2', 'category3'], // Stories only\n  cellType: Storyteller.CellType.round, // StorytellerStoriesRowView only\n  displayLimit: 10,\n  preload: true, // Stories only\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nstoryRow.configuration = storyRowConfiguration;\n</code></pre> <p>For a working React component that applies these options, see the Storyteller Web Showcase's <code>StorytellerStoriesRowView</code>.</p>"},{"location":"StorytellerRowView/#clips-configuration","title":"Clips configuration","text":"JavaScriptTypeScript <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'collection-id'\n);\nclipsRow.configuration = {\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipsRow.cellType = Storyteller.CellType.round; // Clips rows set cellType on the view\n</code></pre> <pre><code>const customTheme = new Storyteller.UiTheme(); // See Customize themes\nconst clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'collection-id'\n);\nconst clipsRowConfiguration: IListConfiguration&lt;'StorytellerClipsRowView'&gt; = {\n  displayLimit: 10,\n  theme: customTheme,\n  uiStyle: Storyteller.UiStyle.dark,\n};\nclipsRow.configuration = clipsRowConfiguration;\nclipsRow.cellType = Storyteller.CellType.round; // Clips rows set cellType on the view\n</code></pre> <p>For Clips, the Storyteller Web Showcase's <code>StorytellerClipsRowView</code> builds the row configuration with the collection ID, display limit, and theme.</p> <p>Rows accept every setting in Configure views, plus the following:</p>"},{"location":"StorytellerRowView/#celltype","title":"cellType","text":"<p><code>cellType</code> sets the tile shape: <code>Storyteller.CellType.square</code> (default) or <code>Storyteller.CellType.round</code>.</p> <ul> <li>On a Stories row, set it in <code>configuration</code>.</li> <li>On a Clips row, set <code>clipsRow.cellType</code>. <code>configuration</code> doesn't accept <code>cellType</code> for Clips rows.</li> <li>On either row, you can instead add <code>data-cell-type=\"round\"</code> to the container.</li> </ul>"},{"location":"Themes/","title":"Customize themes","text":"<p>A theme sets the colors, font, spacing, and controls of Storyteller views and players. You can set a theme in two places:</p> <ul> <li>The global theme, <code>Storyteller.sharedInstance.theme</code>, applies to every   view and player on the page.</li> <li>A view's theme, the <code>theme</code> in that view's <code>configuration</code>, changes one   view and the player it opens.</li> </ul> <p>Both take a <code>UiTheme</code> object. Storyteller also applies a remote theme: theme settings that Storyteller configures for your tenant or for a feed. The remote theme controls captions, compact Clip action buttons, and Clip like and share counts. You can't change these settings with <code>UiTheme</code>.</p>"},{"location":"Themes/#set-the-global-theme","title":"Set the global theme","text":"<p>Set the global theme after <code>initialize</code> resolves:</p> <pre><code>Storyteller.sharedInstance.initialize('demo-api-key').then(() =&gt; {\n  const myTheme = new Storyteller.UiTheme();\n  myTheme.light.colors.primary = '#FF2D00';\n  myTheme.dark.colors.primary = '#FF2D00';\n\n  Storyteller.sharedInstance.theme = myTheme;\n});\n</code></pre> <p>The SDK applies the theme when you assign it, and views that already exist update. If you change a property later, assign the theme again.</p>"},{"location":"Themes/#set-a-views-theme","title":"Set a view's theme","text":"<p>To style one view differently, set <code>theme</code> in its <code>configuration</code>:</p> <pre><code>const storiesRow = new Storyteller.StorytellerStoriesRowView(\n  'storyteller-stories-row',\n  ['category-id']\n);\n\nconst rowTheme = new Storyteller.UiTheme();\nrowTheme.light.lists.row.tileSpacing = 4;\nrowTheme.dark.lists.row.tileSpacing = 4;\n\nstoriesRow.configuration = { theme: rowTheme };\n</code></pre> <p>Learn more</p> <p>For all view configuration options, see Configure views.</p> <p>The Storyteller Web Showcase builds a static theme in <code>buildBasicTheme</code>.</p>"},{"location":"Themes/#theme-precedence","title":"Theme precedence","text":"<p>For each <code>UiTheme</code> property, the SDK uses the first value it finds:</p> <ol> <li>The value in the view's <code>configuration.theme</code></li> <li>The value in the global theme, <code>Storyteller.sharedInstance.theme</code></li> <li>The default value in the tables on this page</li> </ol> <p>The view's theme is merged over the global theme. A view theme value that equals the default doesn't override the global value.</p> <p><code>initialize</code> resets the global theme. Each <code>initialize</code> call, including a call after the user changes, sets <code>Storyteller.sharedInstance.theme</code> back to the defaults. Set the global theme after <code>initialize</code> resolves, and set it again after any later <code>initialize</code> call. A theme in a view's <code>configuration</code> is kept.</p> <p>The remote theme is separate from <code>UiTheme</code>, and <code>UiTheme</code> values don't override it:</p> <ul> <li>Captions: each valid caption field in the feed's remote   theme overrides the same field in the tenant's remote theme. Missing fields   use the tenant value, then the default.</li> <li>Compact Clip action buttons: the feed's   remote theme turns them on. The default is <code>false</code>.</li> <li>Like and share counts: a feed value overrides the tenant   value. The default is <code>true</code>.</li> </ul>"},{"location":"Themes/#configuring-a-uitheme","title":"Configure a UiTheme","text":"<p>A <code>UiTheme</code> has two properties:</p> <ul> <li><code>light</code>: the <code>Theme</code> used in light mode</li> <li><code>dark</code>: the <code>Theme</code> used in dark mode</li> </ul> <p>The view's <code>uiStyle</code> selects which one applies: <code>light</code>, <code>dark</code>, or <code>auto</code>. With <code>auto</code>, the view follows the browser's <code>prefers-color-scheme</code> setting. Set a property in both <code>light</code> and <code>dark</code> when it should not change with the color scheme.</p>"},{"location":"Themes/#creating-themes","title":"Theme properties","text":"<p>The <code>Theme</code> object contains every property you can customize.</p> <p>Some properties take their default value from others. For example, setting <code>colors.primary</code> to <code>#FF0000</code> also colors the unread indicator on rectangular tiles red. The tables mark these properties with \"inherits\".</p> <p>Future SDK versions may use a property for more elements.</p>"},{"location":"Themes/#colors","title":"Colors","text":"<p>The <code>colors</code> property sets the base colors that the SDK uses.</p> Property Default Value Data Type Description <code>primary</code> <code>#1C62EB</code> <code>string</code> - CSS color property The default accent color used throughout the UI. In general, this should be the primary brand color. <code>success</code> <code>#3BB327</code> <code>string</code> - CSS color property Used to indicate correct answers in Quizzes. <code>alert</code> <code>#E21219</code> <code>string</code> - CSS color property Used to indicate incorrect answers in Quizzes. <code>white.primary</code> <code>#FFFFFF</code> <code>string</code> - CSS color property Used for white text <code>white.secondary</code> <code>white.primary</code> at 85% opacity <code>string</code> - CSS color property Used for light text <code>white.tertiary</code> <code>white.primary</code> at 70% opacity <code>string</code> - CSS color property Used for gray text <code>black.primary</code> <code>#1A1A1A</code> <code>string</code> - CSS color property Used for black text <code>black.secondary</code> <code>black.primary</code> at 85% opacity <code>string</code> - CSS color property Used for light black text <code>black.tertiary</code> <code>black.primary</code> at 70% opacity <code>string</code> - CSS color property Used for gray text <code>focusIndicator</code> <code>colors.primary</code> <code>string</code> - CSS color property Used for the focus outlines of interactive elements"},{"location":"Themes/#font","title":"Font","text":"<p>Set <code>font</code> to a CSS <code>font-family</code> value to use a custom font throughout the SDK. The default value is <code>inherit</code>.</p>"},{"location":"Themes/#primitives","title":"Primitives","text":"<p>The <code>primitives</code> object contains base values that the SDK uses throughout.</p> Property Default Value Data Type Description <code>cornerRadius</code> <code>4</code> <code>number</code> The corner radius in pixels used for rectangular tiles, buttons, and Poll/Quiz answers"},{"location":"Themes/#lists","title":"Lists","text":"<p>The <code>lists</code> property sets the layout of rows and grids.</p> Property Default Value Data Type Description <code>lists.backgroundColor</code> inherits <code>colors.white.primary</code> for <code>light</code>, <code>colors.black.primary</code> for <code>dark</code> <code>string</code> - CSS color property Used for the outline on the Live chip and the fade at the sides of a row. <code>lists.row.tileSpacing</code> <code>8</code> <code>number</code> The (external) space between each Story Tile in a row <code>lists.row.startInset</code> <code>12</code> <code>number</code> The (external) space before the first Story Tile in a row <code>lists.row.endInset</code> <code>12</code> <code>number</code> The (external) space after the last Story Tile in a row <code>lists.row.startPadding</code> <code>0</code> <code>number</code> The (internal) space before the first Story Tile in a row <code>lists.row.endPadding</code> <code>0</code> <code>number</code> The (internal) space after the last Story Tile in a row <code>lists.row.showScrollIndicator</code> <code>true</code> <code>boolean</code> Whether the scroll indicator should be visible on non-touch screens (it's always hidden on touch screens) <code>lists.row.scrollIndicatorBackgroundColor</code> <code>white</code> <code>string</code> - CSS color property The background color of the scroll indicator <code>lists.row.scrollIndicatorColor</code> <code>rgba(26, 26, 26, 0.7)</code> <code>string</code> - CSS color property The color of the scroll indicator icon. Ignored if <code>scrollIndicatorIcon</code> is set <code>lists.row.scrollIndicatorIcon</code> <code>undefined</code> <code>string</code> - image URL URL of a custom scroll indicator icon. HTML strings are not supported. <code>lists.row.scrollIndicatorFade</code> <code>true</code> <code>boolean</code> Used to show/hide the fade overlay on the edges of the Story row <code>lists.row.scrollIndicatorInlineAlignment</code> <code>inside</code> <code>inside</code>, <code>outside</code> Whether the scroll arrows should appear on top of the row (<code>inside</code>) or next to it (<code>outside</code>). <code>lists.grid.tileSpacing</code> <code>8</code> <code>number</code> The space between each Story Tile in a grid, both vertically and horizontally <code>lists.grid.columns</code> <code>2</code> <code>number</code> The number of columns in a grid <code>lists.grid.topInset</code> <code>12</code> <code>number</code> The space before the first row in a grid <code>lists.grid.bottomInset</code> <code>12</code> <code>number</code> The space after the last row in a grid <code>lists.grid.startInset</code> <code>16</code> <code>number</code> The space on the left side of a grid <code>lists.grid.endInset</code> <code>16</code> <code>number</code> The space on the right side of a grid"},{"location":"Themes/#story-tiles","title":"Story tiles","text":"<p>The <code>storyTiles</code> property sets the appearance of Story tiles.</p> Property Default Value Data Type Description <code>chip.textSize</code> <code>11</code> <code>number</code> Text size for the New Indicator and Live Indicator <code>chip.show</code> <code>true</code> <code>boolean</code> Used to show/hide the new/live chip <code>title.textSize</code> <code>11</code> <code>number</code> Size of the Story Title on a Tile <code>title.lineHeight</code> <code>13</code> <code>number</code> The line height of the Story Title on a Tile <code>title.alignment</code> <code>center</code> <code>Alignment</code> (<code>Storyteller.Alignment.start</code>, <code>.center</code>, <code>.end</code>) The alignment of the Story Title on a Tile. Possible values are <code>start</code>, <code>center</code> and <code>end</code> <code>title.fontWeight</code> <code>700</code> <code>number</code> The font weight (CSS <code>font-weight</code>) of the Story Title on a Tile <code>circularTile.liveChip.readImage</code> <code>null</code> <code>string</code> - <code>&lt;img&gt;</code> <code>src</code> property Image to be used in place of default read Live Indicator for circular tiles <code>circularTile.liveChip.unreadImage</code> <code>null</code> <code>string</code> - <code>&lt;img&gt;</code> <code>src</code> property Image to be used in place of default unread Live Indicator for circular tiles <code>circularTile.liveChip.readBackgroundColor</code> inherits <code>colors.black.tertiary</code> <code>string</code> - CSS color property Background color of the circular tiles Live Indicator when all Pages have been read <code>circularTile.liveChip.unreadBackgroundColor</code> inherits <code>colors.alert</code> <code>string</code> - CSS color property Background color of the circular tiles Live Indicator when the Story contains unread Pages <code>circularTile.liveChip.unreadBackgroundGradient</code> <code>null</code> <code>string</code> - CSS gradient Background of unread Live and pinned chips on circular tiles. When set, it replaces <code>unreadBackgroundColor</code>. See Live chip gradient and borders <code>circularTile.liveChip.readTextColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property Text color of the circular tiles Live Indicator when all Pages have been read <code>circularTile.liveChip.unreadTextColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property Text color of the circular tiles Live Indicator when the Story contains unread Pages <code>circularTile.liveChip.readBorderColor</code> <code>null</code> <code>string</code> - CSS color property Color of the one-pixel inner border on read Live and pinned chips on circular tiles <code>circularTile.liveChip.unreadBorderColor</code> <code>null</code> <code>string</code> - CSS color property Color of the one-pixel inner border on unread Live and pinned chips on circular tiles <code>circularTile.title.unreadTextColor</code> inherits <code>colors.black.primary</code> for <code>light</code>, <code>colors.white.primary</code> for <code>dark</code> <code>string</code> - CSS color property The text color of the Story Title for a circular tile when the Story is unread <code>circularTile.title.readTextColor</code> inherits <code>colors.black.tertiary</code> for <code>light</code>, <code>colors.white.tertiary</code> for <code>dark</code> <code>string</code> - CSS color property The text color of the Story Title for a circular tile when the Story is read <code>circularTile.unreadIndicatorColor</code> inherits <code>colors.primary</code> <code>string</code> - CSS color property or linear-gradient The color of the ring around a circular tile when the Story is unread <code>circularTile.readIndicatorColor</code> <code>#C5C5C5</code> <code>string</code> - CSS color property or linear-gradient The color of the ring around a circular tile when the Story is read <code>circularTile.unreadStrokeWidth</code> <code>2</code> <code>number</code> (in px) The thickness of the ring around a circular tile when the Story is unread <code>circularTile.readStrokeWidth</code> <code>1</code> <code>number</code> (in px) The thickness of the ring around a circular tile when the Story is read <code>circularTile.scrollIndicatorBlockAlignment</code> <code>cell</code> <code>cell</code>, <code>thumbnail</code> Whether the scroll arrows should be centered with the whole cell (including the titles), or with the thumbnail. <code>rectangularTile.liveChip.readImage</code> <code>null</code> <code>string</code> - <code>&lt;img&gt;</code> <code>src</code> property Image to be used in place of default read Live Indicator for rectangular tiles <code>rectangularTile.liveChip.unreadImage</code> <code>null</code> <code>string</code> - <code>&lt;img&gt;</code> <code>src</code> property Image to be used in place of default unread Live Indicator for rectangular tiles <code>rectangularTile.liveChip.readBackgroundColor</code> inherits <code>colors.black.tertiary</code> <code>string</code> - CSS color property Background color of the rectangular tiles Live Indicator when all Story Pages have been read or the Clip has been viewed <code>rectangularTile.liveChip.unreadBackgroundColor</code> inherits <code>colors.alert</code> <code>string</code> - CSS color property Background color of the rectangular tiles Live Indicator when the Story contains unread Pages or the Clip has not been viewed <code>rectangularTile.liveChip.unreadBackgroundGradient</code> <code>null</code> <code>string</code> - CSS gradient Background of unread Live and pinned chips on rectangular tiles. When set, it replaces <code>unreadBackgroundColor</code>. See Live chip gradient and borders <code>rectangularTile.liveChip.readTextColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property Text color of the rectangular tiles Live Indicator when all Story Pages have been read or the Clip has been viewed <code>rectangularTile.liveChip.unreadTextColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property Text color of the rectangular tiles Live Indicator when the Story contains unread Pages or the Clip has not been viewed <code>rectangularTile.liveChip.readBorderColor</code> <code>null</code> <code>string</code> - CSS color property Color of the one-pixel inner border on read Live and pinned chips on rectangular tiles <code>rectangularTile.liveChip.unreadBorderColor</code> <code>null</code> <code>string</code> - CSS color property Color of the one-pixel inner border on unread Live and pinned chips on rectangular tiles <code>rectangularTile.title.textColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property The text color of the Story Title for a rectangular tile <code>rectangularTile.padding</code> <code>8</code> <code>number</code> The internal padding for a rectangular Story tile <code>rectangularTile.chip.alignment</code> <code>end</code> <code>Alignment</code> (<code>Storyteller.Alignment.start</code>, <code>.center</code>, <code>.end</code>) Alignment of the New Indicator and Live Indicator in Rectangular Tiles, can be <code>start</code>, <code>center</code> or <code>end</code>. <code>rectangularTile.unreadIndicator.image</code> <code>null</code> <code>string</code> - <code>&lt;img&gt;</code> <code>src</code> property An image which can be used in place of the default unread indicator for a rectangular tile <code>rectangularTile.unreadIndicator.backgroundColor</code> inherits <code>colors.primary</code> <code>string</code> - CSS color property The background color of the unread indicator for a rectangular tile <code>rectangularTile.unreadIndicator.textColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property The text color of the unread indicator for a rectangular tile <code>rectangularTile.showWebStoriesIcon</code> <code>false</code> <code>boolean</code> Set this to true to show a Story icon on rectangular thumbnails <code>rectangularTile.showGradient</code> <code>true</code> <code>boolean</code> Set this to <code>false</code> to hide the gradient behind the Story title on rectangular cells"},{"location":"Themes/#live-chip-gradient-and-borders","title":"Live chip gradient and borders","text":"<p>The Stories API can supply <code>customLiveChipText</code> for a Live Story or <code>pinnedChipText</code> for a pinned Story. The SDK uses that text in the Story tile chip. These fields come from Story content; they are separate from <code>UiTheme</code>. Use the chip theme properties below to style their background and border on round or rectangular tiles.</p> <p>Both <code>circularTile.liveChip</code> and <code>rectangularTile.liveChip</code> accept these extra properties:</p> <ul> <li><code>unreadBackgroundGradient</code>: A CSS gradient string. Its default is <code>null</code>. A   set value replaces <code>unreadBackgroundColor</code> on unread Live or pinned chips.</li> <li><code>readBorderColor</code>: A CSS color for the one-pixel inner border on a read Live   or pinned chip. Its default is <code>null</code>.</li> <li><code>unreadBorderColor</code>: A CSS color for the one-pixel inner border on an unread   Live or pinned chip. Its default is <code>null</code>.</li> </ul> <p></p> <p></p>"},{"location":"Themes/#player","title":"Player","text":"<p>The <code>player</code> property sets options for the Story player.</p> Property Default Value Data Type Description <code>disableUrls</code> <code>false</code> <code>boolean</code> Disable the hash URLs when opening a Story. Note that this will also disable sharing. <code>showStoryIcon</code> <code>true</code> <code>boolean</code> Shows the Story icon in the Player <code>showShareButton</code> <code>true</code> <code>boolean</code> Shows the share button in the Player. Setting this to <code>false</code> entirely disables sharing in Storyteller <code>actionButton.icon</code> <code>null</code> <code>string</code> - image URL URL of a 20 \u00d7 20 px custom icon to display in the action buttons. HTML strings are not supported. <code>actionButton.showOnMobile</code> <code>true</code> <code>boolean</code> Shows the action button on top of the player on small screens. If set to <code>false</code>, the action button will only be shown if there is sufficient space to display it underneath the player. <code>actionButton.alignment</code> <code>center</code> <code>ButtonAlignment</code> (<code>Storyteller.ButtonAlignment.left</code>, <code>.center</code>, <code>.right</code>) Sets the alignment of the action button on small screens. Possible values are <code>left</code>, <code>center</code> and <code>right</code>. If there is enough space for the button to sit underneath the player, it will always be centered. <code>icons.back</code> <code>null</code> <code>string</code> - image URL or data string An image to be used in place of the default Clips player back/close icon <code>icons.share</code> <code>null</code> <code>string</code> - image URL or data string Not used by the Web SDK. An image to be used in place of the default share icon <code>playAllStories</code> <code>false</code> <code>boolean</code> Set this to true to stop the player from closing after all unread Stories have been viewed <p></p>"},{"location":"Themes/#clip-player","title":"Clips player","text":"<p>The <code>clipPlayer</code> property sets options for the Clips player.</p> <p>To change the back or close icon at the top left of the Clips player, use <code>player.icons.back</code>.</p> Property Default Value Data Type Description <code>disableUrls</code> <code>false</code> <code>boolean</code> Disable the hash URLs when opening a Clip. Note that this will also disable sharing. <code>showShareButton</code> <code>true</code> <code>boolean</code> Shows the share button in the Player. Setting this to <code>false</code> entirely disables sharing. <code>showLikeButton</code> <code>true</code> <code>boolean</code> Shows the like button in the Player. <code>showFeedTitle</code> <code>true</code> <code>boolean</code> Shows the feed title or feed title image in the Clips player header. <code>showClipTitle</code> <code>true</code> <code>boolean</code> Shows the active Clip title in the Clips player metadata. <code>showNavigationCategories</code> <code>true</code> <code>boolean</code> Shows Clip navigation categories and the active category title in the Clips player header. <p>The remote theme sets whether the Clips player shows like and share counts. A feed's <code>showLikeCount</code> or <code>showShareCount</code> value overrides the tenant value for that feed. If the feed doesn't set a field, the tenant value applies, and then the default, <code>true</code>. <code>UiTheme</code> doesn't include these fields. Before version 11.0, the SDK ignored them, so tenants whose remote theme already sets them see the change after the update.</p> <p><code>showClipTitle: false</code> hides the Clip title. A long description supplied with the Clip remains available in the expandable details.</p>"},{"location":"Themes/#compact-clip-action-buttons","title":"Compact Clip action buttons","text":"<p>The remote theme field <code>behavior.player.clipsActionButtonCompactSize</code> sets the size of Clip action buttons. When it is <code>true</code>, the Clips player shows smaller action buttons in the Clip details area. When it is <code>false</code>, the buttons span the width below the Clip. If the remote theme doesn't set it, the value is <code>false</code>.</p> <p>To change it, ask Storyteller to set it for the feed. Before version 11.0, the SDK ignored this field, so feeds that already set it show compact buttons after the update. <code>UiTheme</code> still sets the button styles through <code>player.actionButton</code> and <code>buttons</code>.</p>"},{"location":"Themes/#closed-captions","title":"Captions","text":"<p>Captions stay off until Storyteller turns them on for Stories, Clips, or both. The CC button then appears on Clips and on supported Story Pages, even when the content has no caption track. It stays available while a track loads and after an empty or failed response. A missing or unavailable track does not interrupt playback. Ads and Poll or Quiz Pages hide the CC button.</p> <p>Caption text appears when a Clip or Story Page has a WebVTT track with an active cue. Clip captions appear after the Clip starts playing and stay visible while it is paused. Clips that are preloaded or not in view keep their captions hidden. Live Clips show the CC button but no caption text.</p> <p>The user's caption choice applies to both Clips and Stories. When functional cookies are allowed (<code>enableFunctionalCookies</code>, see Control privacy and tracking), the SDK stores the choice in the browser. Otherwise, the choice lasts until the page reloads.</p> <p>Story captions appear near the top of each supported Page. Poll and Quiz Pages hide both the caption text and the CC button. The CC button sits 16 px from the lower-right corner of the Story. On a Page with an action button, it moves up to 72 px from the bottom. Caption text changes as soon as the next cue starts.</p> <p>Caption styling comes from the remote theme, not from <code>UiTheme</code>. Each valid caption field in the feed's remote theme overrides the same field in the tenant's remote theme. A missing or invalid feed field uses the tenant value, then the default in the table below. The horizontal and vertical padding follow this rule separately.</p> <p>Version 11.0 changed this behavior. Earlier versions used the feed's caption settings as one object whenever the feed had them, and their defaults were 18 px text, a 22 px line height, and a <code>#000000</code> background. If your captions relied on those defaults, check them after you update.</p> <p>Captions align to the start edge of the surrounding text direction: left for LTR and right for RTL. Each rendered line has its own background, including lines created by wrapping. The background height includes the text line height and vertical padding. A 2 px gap separates consecutive backgrounds.</p> <p><code>lineHeight</code> controls the text area. The SDK adds padding and the gap when it places the next line. Padding and corner radius accept zero.</p> Remote theme field Default value Description <code>font</code> System font stack Caption font family, with system-font fallback <code>textSize</code> <code>16</code> Font size in pixels <code>lineHeight</code> Natural font height Line height in pixels <code>textColor</code> <code>#FFFFFF</code> Caption text color <code>backgroundColor</code> <code>#171A25</code> Caption background color <code>backgroundOpacity</code> <code>0.65</code> Background opacity from <code>0</code> to <code>1</code> <code>padding.horizontal</code> <code>10</code> Left and right padding in pixels <code>padding.vertical</code> <code>4</code> Top and bottom padding in pixels <code>cornerRadius</code> <code>8</code> Background corner radius in pixels"},{"location":"Themes/#buttons","title":"Buttons","text":"<p>The <code>buttons</code> property sets the style of buttons throughout the SDK.</p> Property Default Value Data Type Description <code>backgroundColor</code> inherits <code>colors.white.primary</code> <code>string</code> - CSS color property The background color of buttons throughout the SDK <code>textColor</code> inherits <code>colors.black.primary</code> <code>string</code> - CSS color property The text color of buttons throughout the SDK <code>textCase</code> <code>default</code> <code>TextCase</code> (<code>Storyteller.TextCase.upper</code>, <code>.lower</code>, <code>.default</code>) Sets the text case for buttons throughout the SDK. Possible values are <code>upper</code>, <code>lower</code> and <code>default</code> <code>cornerRadius</code> inherits <code>primitives.cornerRadius</code> <code>number</code> The corner radius for all buttons throughout the SDK"},{"location":"Themes/#instructions","title":"Instructions","text":"<p>The <code>instructions</code> property sets the appearance of the instructions screen.</p> Property Default Value Data Type Description <code>show</code> <code>true</code> <code>boolean</code> Determines whether the Instructions Screen is shown the first time a user opens the Story player. Set to <code>false</code> to completely disable the instructions screen. <code>headingColor</code> inherits <code>colors.black.primary</code> for <code>light</code>, <code>colors.white.primary</code> for <code>dark</code> <code>string</code> - CSS color property The color of the heading text on the Instructions Screen <code>iconColor</code> inherits <code>headingColor</code> <code>string</code> - CSS color property The foreground color of the built-in instruction icons <code>iconHighlightColor</code> inherits <code>colors.primary</code> <code>string</code> - CSS color property The highlight color of the built-in instruction icons <code>subHeadingColor</code> inherits <code>colors.black.secondary</code> for <code>light</code>, <code>colors.white.secondary</code> for <code>dark</code> <code>string</code> - CSS color property The color of the subheading text on the Instructions Screen <code>backgroundColor</code> inherits <code>colors.white.primary</code> for <code>light</code>, <code>colors.black.primary</code> for <code>dark</code> <code>string</code> - CSS color property The color of the background of the Instructions Screen <code>icons</code> <code>{}</code> object with optional <code>forward</code>, <code>back</code>, <code>swipe</code>, <code>pause</code> image URLs A set of custom icons to be used for each instruction on the Instructions Screen <code>button.backgroundColor</code> inherits <code>colors.black.primary</code> for <code>light</code>, <code>colors.white.primary</code> for <code>dark</code> <code>string</code> - CSS color property The background color of the button used on the Instructions Screen <code>button.textColor</code> inherits <code>colors.white.primary</code> for <code>light</code>, <code>colors.black.primary</code> for <code>dark</code> <code>string</code> - CSS color property The text color of the button used on the Instructions Screen <p><code>iconColor</code> and <code>iconHighlightColor</code> recolor every built-in instruction icon. This includes the pointer icons on non-touch devices and the touch and swipe icons on touch devices. By default, the icon color follows <code>headingColor</code> and the highlight follows <code>colors.primary</code>. These properties don't change the heading or subheading text colors.</p> <pre><code>const theme = new Storyteller.UiTheme();\n\ntheme.light.colors.primary = '#ff2d00'; // Built-in icon highlights inherit this\ntheme.light.instructions.iconColor = '#2b2929';\ntheme.dark.instructions.iconColor = '#f5f2f2';\n\nStoryteller.sharedInstance.theme = theme;\n</code></pre> <p>Use <code>icons</code> to replace the image for any instruction. A custom image replaces the built-in icon and its theme colors for that instruction. Built-in icons without a custom image still follow the theme colors. Use 48 \u00d7 48 px PNG images:</p> <pre><code>const theme = new Storyteller.UiTheme();\nconst customIcons = {\n  forward: './icon-forward-custom.png',\n  pause: './icon-pause-custom.png',\n  back: './icon-back-custom.png',\n  swipe: './icon-swipe-custom.png',\n};\n\ntheme.light.instructions.icons = customIcons;\ntheme.dark.instructions.icons = customIcons;\n\nStoryteller.sharedInstance.theme = theme;\n</code></pre> <p></p>"},{"location":"Themes/#engagement-units","title":"Polls and Quizzes (<code>engagementUnits</code>)","text":"<p>The <code>engagementUnits</code> property sets the style of Polls and Quizzes.</p> Property Default Value Data Type Description <code>poll.answerTextColor</code> inherits <code>colors.black.primary</code> <code>string</code> - CSS color property The text color used for Poll Answers <code>poll.percentBarColor</code> <code>#CDD0DC</code> <code>string</code> - CSS color property The background color of the percentage bar in Poll Answers <code>poll.selectedAnswerBorderColor</code> inherits <code>colors.white.tertiary</code> <code>string</code> - CSS color property The border color applied to the selected Poll Answer <code>poll.answeredMessageTextColor</code> inherits <code>colors.white.tertiary</code> <code>string</code> - CSS color property The color of the vote count shown to users after they select a Poll Answer <code>poll.selectedAnswerBorderImage</code> <code>null</code> <code>string</code> or <code>null</code> Not used by the Web SDK. A border image for the selected Poll Answer. The Web SDK uses <code>selectedAnswerBorderColor</code> <code>poll.showVoteCount</code> <code>true</code> <code>boolean</code> Shows the approximate number of Poll Answers after a user selects an answer. If this is set to <code>false</code>, the message \"Thanks for voting!\" is displayed instead <code>poll.showPercentBarBackground</code> <code>false</code> <code>boolean</code> Not used by the Web SDK. Adds a striped background under the percentage bar in Poll Answers <code>triviaQuiz.correctColor</code> inherits <code>colors.success</code> <code>string</code> - CSS color property The color used to show correct answers in Quizzes <code>triviaQuiz.incorrectColor</code> inherits <code>colors.alert</code> <code>string</code> - CSS color property The color used to show incorrect answers in Quizzes <p></p> <p></p>"},{"location":"Themes/#example","title":"Example","text":"<pre><code>const theme = new Storyteller.UiTheme({\n  light: {\n    colors: {\n      primary: 'blue',\n      success: 'green',\n    },\n  },\n});\n\n// Setting theme by direct property access\ntheme.light.colors.primary = 'red';\n\n// Applying light/dark mode specific values\ntheme.light.instructions.headingColor = 'black';\ntheme.dark.instructions.headingColor = 'white';\n\nStoryteller.sharedInstance.theme = theme;\n</code></pre>"},{"location":"Users/","title":"Identify and personalize users","text":"<p>The SDK keeps a user ID in the browser to remember what each user has read, liked, voted on, and answered. This page shows how to use your own user IDs, change users, set user attributes for personalization, and set the Clips language.</p>"},{"location":"Users/#user-ids","title":"User IDs","text":"<p>If you don't pass an <code>externalId</code> the first time you call <code>initialize</code>, the SDK creates an anonymous user ID and stores it in the browser's local storage. With the default privacy options, the SDK uses this ID to keep track of:</p> <ul> <li>which Pages the user has read</li> <li>which Polls the user has voted in</li> <li>which Quizzes the user has answered</li> <li>which Clips the user has liked or viewed</li> </ul> <p>You don't need extra code for this. Initialize the SDK:</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key');\n</code></pre> <p>Note</p> <p>Replace <code>demo-api-key</code> with your Storyteller Web SDK API key. To request one, email hello@getstoryteller.com.</p>"},{"location":"Users/#setting-a-user-id","title":"Set a user ID","text":"<p>If your site has user accounts, pass your own user ID as <code>externalId</code> in the second <code>initialize</code> argument:</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key', {\n  externalId: 'your-user-id',\n});\n</code></pre> <p>With the default privacy options, <code>initialize</code> loads the viewing history that Storyteller saved for this ID: read Pages, Clip likes and views, and Poll and Quiz answers. The history follows the user to every browser and device where they sign in with the same <code>externalId</code>.</p> <p>Use an ID that is unique to the user and never changes, such as your account ID. Avoid values that can change, such as an email address.</p> <p>Call <code>initialize</code> as soon as you know the <code>externalId</code>, for example on page load or when a user signs in.</p> <p>Note</p> <p>The SDK hashes the <code>externalId</code> before it stores or sends it, to support Video Privacy Protection Act (VPPA) compliance.</p>"},{"location":"Users/#changing-users","title":"Change users","text":"<p>When a user signs out, or another user signs in, call <code>initialize</code> again with the new <code>externalId</code>. Pass <code>null</code> when the user continues anonymously. A call without <code>externalId</code> keeps the current user ID, so it doesn't sign a user out.</p> <pre><code>async function onSignIn(userId) {\n  await Storyteller.sharedInstance.initialize('demo-api-key', {\n    externalId: userId,\n  });\n}\n\nasync function onSignOut() {\n  await Storyteller.sharedInstance.initialize('demo-api-key', {\n    externalId: null,\n  });\n}\n</code></pre> <p>When the user ID changes, the SDK:</p> <ul> <li>clears the stored user attributes</li> <li>clears the read status, likes, and answers of the previous user</li> <li>loads the viewing history that Storyteller saved for the new user ID; with   <code>null</code>, the user starts with an empty history</li> </ul> <p>Every <code>initialize</code> call also resets <code>Storyteller.sharedInstance.theme</code> to its defaults. Set the global theme again after the call resolves. A theme set in a view's <code>configuration</code> is kept.</p>"},{"location":"Users/#sample-code-for-user-ids","title":"Sample code for user IDs","text":"<p>The Storyteller Web Showcase's <code>persistUserIdAndReload</code> helper shows how to store, clear, and apply a user ID.</p>"},{"location":"Users/#personalization-and-targeted-stories","title":"Personalization and targeted Stories","text":"<p>User attributes let you personalize rows and grids and target Stories to groups of users. For more information, see Personalization and Audience Targeting in the Storyteller User Guide.</p>"},{"location":"Users/#setting-user-attributes","title":"Set user attributes","text":"<p>To set a user attribute, call <code>setUserAttribute</code> on <code>Storyteller.User</code> with the attribute key and its value. For example, to set the user's location:</p> <pre><code>Storyteller.User.setUserAttribute('location', 'New York');\n</code></pre> <p>The SDK adds the attribute, with the key <code>location</code> and the value <code>New York</code>, to its requests to Storyteller. Use it to personalize or target Stories in the Storyteller CMS.</p> <p>To set more attributes, call <code>setUserAttribute</code> once for each key. Keys and values must be non-empty strings; otherwise the method throws an error. When <code>enablePersonalization</code> is <code>false</code>, the SDK doesn't store attributes.</p> <p>Note</p> <p>Set user attributes after <code>initialize</code> resolves. A user change during <code>initialize</code> clears them.</p>"},{"location":"Users/#removing-user-attributes","title":"Remove user attributes","text":"<p>To remove a user attribute, call <code>removeUserAttribute</code> on <code>Storyteller.User</code> with the attribute key. For example, to remove the user's location:</p> <pre><code>Storyteller.User.removeUserAttribute('location');\n</code></pre> <p>Note</p> <p>When a user signs out and you don't call <code>initialize</code> again, remove each attribute you set.</p>"},{"location":"Users/#updating-the-clips-locale","title":"Update the Clips locale","text":"<p>To set the language for Clips, call <code>setLocale</code> on <code>Storyteller.User</code> with a language code. For example, to set the language to Spanish:</p> <pre><code>Storyteller.User.setLocale('es');\n</code></pre> <p>The SDK stores the language code as the <code>stLocale</code> user attribute, so it follows the same rules as other user attributes.</p>"},{"location":"Users/#sample-code-for-user-attributes","title":"Sample code for user attributes","text":"<p>The Storyteller Web Showcase's <code>persistAndApplyAttributeValues</code> helper shows how to use these user attributes.</p>"},{"location":"analytics/AdEvents/","title":"Ad Events","text":"<p>This page lists the ad events that the SDK sends to <code>onUserActivityOccurred</code>, when each one is recorded, and its properties. The Storyteller Web Showcase handles these events in its <code>onUserActivityOccurred</code> handler.</p> <p>The tables list the properties of ads shown in Stories. Ads shown in Clips include <code>collection</code>, <code>clipHasAction</code>, <code>clipActionText</code>, and <code>clipActionUrl</code> instead of <code>categories</code>, <code>categoryDetails</code>, <code>currentCategory</code>, <code>pageHasAction</code>, <code>pageActionText</code>, and <code>pageActionUrl</code>. For those ads, <code>adType</code> is <code>clips</code> and <code>adPlacement</code> is <code>betweenClips</code>.</p>"},{"location":"analytics/AdEvents/#opened-ad-openedad","title":"Opened Ad (<code>openedAd</code>)","text":"<p>The <code>openedAd</code> event is recorded when:</p> <ul> <li>An Ad is loaded because the previous Story finished</li> <li>A user swipes left on a Story to go to the next Story and an Ad appears</li> <li>A user swipes right on a Story to go to the previous Story and an Ad appears</li> <li>An Ad is loaded because the previous Page finished and an Ad should appear next</li> <li>A user taps to skip to the next Page and an Ad should appear next</li> <li>A user taps to skip to the previous Page and an Ad should appear</li> <li>A user swipes to an Ad in the Clips player</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Content Length <code>contentLength</code> In milliseconds, the total duration of the Page content. 15000, 41000, 32000 Opened Reason <code>openedReason</code> The action which the user took to open the ad. OpenedReason Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#dismissed-ad-dismissedad","title":"Dismissed Ad (<code>dismissedAd</code>)","text":"<p>The <code>dismissedAd</code> event is recorded when:</p> <ul> <li>A user taps close to dismiss the Ad</li> <li>A user swipes down to dismiss the Ad</li> <li>A user presses the browser back button, or leaves the page, while an Ad is showing</li> <li>A user taps to skip the Ad if the Ad is the last Page in the current set of Stories</li> <li>A user swipes left on the Ad if the Ad is the last Page in the current set of Stories</li> <li>A user completes the Ad if the Ad is the last Page in the current set of Stories</li> <li>A user closes the Clips player while an Ad is showing</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Content Length <code>contentLength</code> In milliseconds, the total duration of the Page content. 15000, 41000, 32000 Dismissed Reason <code>dismissedReason</code> The reason the ad was dismissed. DismissedReason Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#paused-ad-page-pausedadpage","title":"Paused Ad Page (<code>pausedAdPage</code>)","text":"<p>The <code>pausedAdPage</code> event is recorded when a user pauses a Page within an Ad by pressing and holding on the Page, or by using the Story playback controls.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#resumed-ad-page-resumedadpage","title":"Resumed Ad Page (<code>resumedAdPage</code>)","text":"<p>The <code>resumedAdPage</code> event is recorded when a user resumes playing a Page within an Ad by releasing their long press which paused the Ad, or by using the Story playback controls.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#finished-ad-finishedad","title":"Finished Ad (<code>finishedAd</code>)","text":"<p>The <code>finishedAd</code> event is recorded at the same time as <code>dismissedAd</code>, <code>skippedAd</code>, and <code>viewedAdPageComplete</code>, and gives an easier way to determine when an ad finishes for any reason. In the Clips player, it is also recorded when a user swipes away from an Ad.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#skipped-ad-skippedad","title":"Skipped Ad (<code>skippedAd</code>)","text":"<p>The <code>skippedAd</code> event is recorded when:</p> <ul> <li>A user swipes left to go to the next Story before completing the current Ad</li> <li>A user swipes right on the Ad to skip to the previous Story before completing the current Ad</li> <li>A user taps on an Ad to go to the next Page or Story before completing the current Ad</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#ad-action-button-tapped-adactionbuttontapped","title":"Ad Action Button Tapped (<code>adActionButtonTapped</code>)","text":"<p>The <code>adActionButtonTapped</code> event is recorded when:</p> <ul> <li>A user swipes up on an Ad to open a link</li> <li>A user taps on the swipe up element of an Ad to open a link</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#viewed-ad-page-first-quartile-viewedadpagefirstquartile","title":"Viewed Ad Page First Quartile (<code>viewedAdPageFirstQuartile</code>)","text":"<p>The <code>viewedAdPageFirstQuartile</code> event is recorded when a user reaches 1/4 of the way through the duration of an Ad Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#viewed-ad-page-midpoint-viewedadpagemidpoint","title":"Viewed Ad Page Midpoint (<code>viewedAdPageMidpoint</code>)","text":"<p>The <code>viewedAdPageMidpoint</code> event is recorded when a user reaches halfway through the duration of an Ad Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#viewed-ad-page-third-quartile-viewedadpagethirdquartile","title":"Viewed Ad Page Third Quartile (<code>viewedAdPageThirdQuartile</code>)","text":"<p>The <code>viewedAdPageThirdQuartile</code> event is recorded when a user reaches 3/4 of the way through the duration of an Ad Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/AdEvents/#viewed-ad-page-complete-viewedadpagecomplete","title":"Viewed Ad Page Complete (<code>viewedAdPageComplete</code>)","text":"<p>The <code>viewedAdPageComplete</code> event is recorded when a user reaches the end of the duration of an Ad Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Ad ID <code>adId</code> The ID of the Ad for which the event occurred. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Ad Placement <code>adPlacement</code> The placement of the ad which is being presented to the user. <code>betweenClips</code>, <code>betweenPages</code>, <code>betweenStories</code>, <code>betweenStoriesAndPages</code> Ad Strategy <code>adStrategy</code> The placement of the ad as a display label. <code>Between Clips</code>, <code>Between Pages</code>, <code>Between Stories</code>, <code>Between Stories and Pages</code> Ad Type <code>adType</code> Whether the ad appeared in Stories or Clips. <code>stories</code>, <code>clips</code> Advertiser Name <code>advertiserName</code> The advertiser name of the Ad for which the event occurred. If no name is supplied, the advertiser URL will be used. <code>Disney+</code>, <code>Hulu</code>, <code>https://nike.com</code>, \u2026 Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the ad event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page Action Text <code>pageActionText</code> If the ad associated with the event has an action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the ad associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/","title":"Clip Events","text":"<p>This page lists the Clip events that the SDK sends to <code>onUserActivityOccurred</code>, when each one is recorded, and its properties. The Storyteller Web Showcase handles these events in its <code>onUserActivityOccurred</code> handler.</p> <p>In <code>openedClip</code>, <code>dismissedClip</code>, and <code>finishedClip</code>, <code>categories</code> holds the names of the Clip's categories. In the other Clip events, it holds the categories' external IDs. Use <code>categoryDetails</code> when you need both.</p>"},{"location":"analytics/ClipEvents/#caption-state-and-events","title":"Caption state and events","text":"<p>Clip activity callbacks include a <code>captionsEnabled</code> boolean with the caption choice at the time of the event. Stories and Clips share that choice. The SDK saves it in the browser when functional storage is allowed. With functional storage disabled, the choice lasts until the page reloads.</p> <p>The player also records an event when the user changes that choice:</p> <ul> <li><code>enabledClipCaptions</code> when the user turns captions on</li> <li><code>disabledClipCaptions</code> when the user turns captions off</li> </ul> <p>Both events contain the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions are enabled after the interaction. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The Clip's one-based index in the active feed. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> The Clip's Call To Action text, when present. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> The URL associated with the Clip's Action, when present. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#opened-clip-openedclip","title":"Opened Clip (<code>openedClip</code>)","text":"<p>The <code>openedClip</code> event is recorded when:</p> <ul> <li>A user taps on a row or grid item to open a Clip</li> <li>A user swipes up to the next Clip</li> <li>A user swipes down to the previous Clip</li> <li>A user is sent directly to a Clip by a call to <code>openCollection</code></li> <li>A user is sent directly to a Clip by a deep link</li> <li>A user dismisses the last Category (by pressing back) and returns to the top level Collection</li> </ul> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Clip for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Content Length <code>contentLength</code> In seconds, the total duration of the Clip. <code>15</code>, <code>21</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Opened Reason <code>openedReason</code> The action which the user took to open the Clip. OpenedReason"},{"location":"analytics/ClipEvents/#dismissed-clip-dismissedclip","title":"Dismissed Clip (<code>dismissedClip</code>)","text":"<p>The <code>dismissedClip</code> event is recorded when 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).</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Clip for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Dismissed Reason <code>dismissedReason</code> The reason the Clip was dismissed. DismissedReason Clips Viewed <code>clipsViewed</code> The total number of Clips a user has viewed since the most recent <code>openedClip</code> event with an <code>openedReason</code> of <code>clipListTap</code> or <code>deepLink</code>. 1, 2, 3, \u2026 Duration Viewed <code>durationViewed</code> In milliseconds, the duration the user viewed the Clips player for, measured from the most recent <code>openedClip</code> event with an <code>openedReason</code> of <code>clipListTap</code> or <code>deepLink</code>. 1200, \u2026 Loops Viewed <code>loopsViewed</code> The total number of loops (plays of an individual Clip) a user has viewed since the most recent <code>openedClip</code> event with an <code>openedReason</code> of <code>clipListTap</code> or <code>deepLink</code>. 1, 2, 3, \u2026"},{"location":"analytics/ClipEvents/#finished-clip-finishedclip","title":"Finished Clip (<code>finishedClip</code>)","text":"<p>The <code>finishedClip</code> event is recorded at the same time as <code>openedCategory</code>, <code>dismissedClip</code>, <code>nextClip</code>, or <code>previousClip</code>.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Clip for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Content Length <code>contentLength</code> In seconds, the total duration of the Clip. <code>15</code>, <code>21</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Duration Viewed <code>durationViewed</code> In milliseconds, the duration the user viewed the Clips player for, measured from the most recent <code>openedClip</code> event with an <code>openedReason</code> of <code>swipe</code>. 1200, \u2026 Loops Viewed <code>loopsViewed</code> The total number of loops (plays of an individual Clip) a user has viewed since the most recent <code>openedClip</code> event with an <code>openedReason</code> of <code>swipe</code>. 1, 2, 3, \u2026"},{"location":"analytics/ClipEvents/#next-clip-nextclip","title":"Next Clip (<code>nextClip</code>)","text":"<p>The <code>nextClip</code> event is recorded when a user swipes up to go to the next Clip.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#previous-clip-previousclip","title":"Previous Clip (<code>previousClip</code>)","text":"<p>The <code>previousClip</code> event is recorded when a user swipes down to go to the previous Clip.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#completed-loop-completedloop","title":"Completed Loop (<code>completedLoop</code>)","text":"<p>The <code>completedLoop</code> event is recorded when a user completes a loop of a Clip. It is never recorded for live Clips.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#action-button-tapped-actionbuttontapped","title":"Action Button Tapped (<code>actionButtonTapped</code>)","text":"<p>The <code>actionButtonTapped</code> event is recorded when a user taps the action button at the bottom of a Clip.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#share-button-tapped-sharebuttontapped","title":"Share Button Tapped (<code>shareButtonTapped</code>)","text":"<p>The <code>shareButtonTapped</code> event is recorded when a user taps the share button on a Clip.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#share-success-sharesuccess","title":"Share Success (<code>shareSuccess</code>)","text":"<p>The <code>shareSuccess</code> event is recorded when a user successfully shares a Clip.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Share Method <code>shareMethod</code> Always an empty string for Clips. <code>''</code>"},{"location":"analytics/ClipEvents/#paused-clip-pausedclip","title":"Paused Clip (<code>pausedClip</code>)","text":"<p>The <code>pausedClip</code> event is recorded when a user taps on the screen while a Clip is playing to pause the Clip. It is not recorded when a Clip pauses automatically because the user shares it or follows an action. It is never recorded for live Clips, because live Clips cannot be paused or resumed.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#resumed-clip-resumedclip","title":"Resumed Clip (<code>resumedClip</code>)","text":"<p>The <code>resumedClip</code> event is recorded when a user taps a paused Clip to resume playback. It is not recorded when a Clip resumes automatically, for example after the user finishes sharing it. It is never recorded for live Clips, because live Clips cannot be paused or resumed.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#liked-clip-likedclip","title":"Liked Clip (<code>likedClip</code>)","text":"<p>The <code>likedClip</code> event is recorded when a user taps the like button on a Clip they have not liked.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#unliked-clip-unlikedclip","title":"Unliked Clip (<code>unlikedClip</code>)","text":"<p>The <code>unlikedClip</code> event is recorded when a user taps the like button on a Clip they have liked.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Clip. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#opened-category-openedcategory","title":"Opened Category (<code>openedCategory</code>)","text":"<p>The <code>openedCategory</code> event is recorded when:</p> <ul> <li>A user taps a Category at the bottom of the Clips player to open a new Category</li> <li>A user opens a Category by navigating back from another Category</li> </ul> <p>Opening the Clips player with <code>openCollection(collectionId, { categoryId })</code> shows the Clips of that Category without recording this event.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list with the Category Detail object of the Category being navigated to. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Category ID <code>categoryId</code> The ID of the Category being navigated to. <code>012200025</code>, <code>12312452</code>, \u2026 Category Name <code>categoryName</code> The name of the Category being navigated to. \u201cMust See Moments\u201d, \u201cRapid Replay\u201d, \u2026 Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/ClipEvents/#dismissed-category-dismissedcategory","title":"Dismissed Category (<code>dismissedCategory</code>)","text":"<p>The <code>dismissedCategory</code> event is recorded when a user navigates back to the previous Category with the back button. It is not recorded when the user dismisses the top level Collection.</p> <p>The event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the external IDs of the categories assigned to the Clip for which the event occurred. [\"game-0012200025\", \"recap\"] Category Details <code>categoryDetails</code> A list with the Category Detail object of the Category being dismissed. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Category ID <code>categoryId</code> The ID of the Category being dismissed. <code>012200025</code>, <code>12312452</code>, \u2026 Category Name <code>categoryName</code> The name of the Category being dismissed. \u201cMust See Moments\u201d, \u201cRapid Replay\u201d, \u2026 Collection <code>collection</code> The ID of the Collection, if the Clip is being played from one. <code>live-stories</code>, <code>top-stories</code>, \u2026 Clip ID <code>clipId</code> The ID of the Clip for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Clip Index <code>clipIndex</code> The index of the Clip in the row or grid at the point it was selected, or the index of the Clip in the feed at the point it was viewed (if the Clip wasn\u2019t opened from a row or grid). This property uses 1-based indexing. 1, 2, 3, \u2026 Clip Title <code>clipTitle</code> The title of the Clip for which the event occurred. \"Highlights\", \"Tonight's Movies\" Clip Has Action <code>clipHasAction</code> Whether the Clip associated with the event contains an Action. <code>true</code>, <code>false</code> Clip Action Text <code>clipActionText</code> If the Clip associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cWatch Now\u201d, \u2026 Clip Action URL <code>clipActionUrl</code> If the Clip associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code>"},{"location":"analytics/PollEvents/","title":"Poll Events","text":"<p>This page lists the Poll event that the SDK sends to <code>onUserActivityOccurred</code>, when it is recorded, and its properties. The Storyteller Web Showcase handles these events in its <code>onUserActivityOccurred</code> handler.</p>"},{"location":"analytics/PollEvents/#voted-poll-votedpoll","title":"Voted Poll (<code>votedPoll</code>)","text":"<p>The <code>votedPoll</code> event is recorded when a user votes in a Poll.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Poll Answer ID <code>pollAnswerId</code> The ID of the Answer the user selected as their vote. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cGame Day: 532CE Greens v Blues\u201d"},{"location":"analytics/QuizEvents/","title":"Quiz Events","text":"<p>This page lists the Quiz events that the SDK sends to <code>onUserActivityOccurred</code>, when each one is recorded, and its properties. The Storyteller Web Showcase handles these events in its <code>onUserActivityOccurred</code> handler.</p>"},{"location":"analytics/QuizEvents/#trivia-quiz-question-answered-triviaquizquestionanswered","title":"Trivia Quiz Question Answered (<code>triviaQuizQuestionAnswered</code>)","text":"<p>The <code>triviaQuizQuestionAnswered</code> event is recorded when:</p> <ul> <li>A user answers a question in a Trivia Quiz</li> <li>A user times out on a question</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cGame Day: 532CE Greens v Blues\u201d Trivia Quiz Answer ID <code>triviaQuizAnswerId</code> The ID of the Trivia Quiz Answer the user selects. If the user times out or exits the Story view, this should be an empty GUID. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Trivia Quiz ID <code>triviaQuizId</code> The ID of the Trivia Quiz with which the user is interacting. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Trivia Quiz Question ID <code>triviaQuizQuestionId</code> The ID of the Trivia Quiz question with which the user is interacting. <code>9c1d7e62-4a5b-4f0e-8d3a-2b6f1c0e7a94</code> Trivia Quiz Title <code>triviaQuizTitle</code> The Title of the Trivia Quiz with which the user is interacting. \u201cWho is the greatest quarterback of all time?\u201d"},{"location":"analytics/QuizEvents/#trivia-quiz-completed-triviaquizcompleted","title":"Trivia Quiz Completed (<code>triviaQuizCompleted</code>)","text":"<p>The <code>triviaQuizCompleted</code> event is recorded when a user completes a Trivia Quiz. It therefore fires at the same time as the final <code>triviaQuizQuestionAnswered</code> event for that Quiz, and is only fired once per user per Quiz.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cGame Day: 532CE Greens v Blues\u201d Trivia Quiz ID <code>triviaQuizId</code> The ID of the Trivia Quiz with which the user is interacting. <code>be772f10-177e-4754-ac09-f91cb547316f</code> Trivia Quiz Score <code>triviaQuizScore</code> The score of the Trivia Quiz, once completed. 2, 5, 9 Trivia Quiz Title <code>triviaQuizTitle</code> The Title of the Trivia Quiz with which the user is interacting. \u201cWho is the greatest quarterback of all time?\u201d"},{"location":"analytics/StoryEvents/","title":"Story Events","text":"<p>This page lists the Story events that the SDK sends to <code>onUserActivityOccurred</code>, when each one is recorded, and its properties. The Storyteller Web Showcase handles these events in its <code>onUserActivityOccurred</code> handler.</p>"},{"location":"analytics/StoryEvents/#caption-state-and-events","title":"Caption state and events","text":"<p>Story and Page activity callbacks that identify a Story or Page include a <code>captionsEnabled</code> boolean. The value records the caption choice when the event occurs. Stories and Clips share that choice. The SDK saves it in the browser when functional storage is allowed. With functional storage disabled, the choice lasts until the page reloads.</p> <p>The player emits <code>enabledStoryCaptions</code> for an enabled choice or <code>disabledStoryCaptions</code> for a disabled choice. Each toggle event includes the resulting <code>captionsEnabled</code> value, plus the active Story and Page identifiers, titles, one-based indexes, category information, and Page action fields.</p> Event property Value in a Story caption toggle event <code>captionsEnabled</code> <code>true</code> or <code>false</code> for the resulting choice. <code>categories</code> Names of the categories assigned to the Story. <code>categoryDetails</code> A list of objects with <code>name</code>, <code>id</code>, <code>type</code>, and optional <code>externalId</code> and string <code>placement</code>. <code>currentCategory</code> An object with <code>title</code>, optional <code>id</code>, and optional string <code>placement</code>. <code>storyId</code>, <code>storyTitle</code>, <code>storyDisplayTitle</code>, <code>storyIndex</code>, <code>storyPageCount</code> The active Story and its one-based index. <code>pageId</code>, <code>pageTitle</code>, <code>pageType</code>, <code>pageIndex</code> The active Page and its one-based index. <code>pageHasAction</code>, <code>pageActionText</code>, <code>pageActionUrl</code> Action details for the active Page."},{"location":"analytics/StoryEvents/#opened-story-openedstory","title":"Opened Story (<code>openedStory</code>)","text":"<p>The <code>openedStory</code> event is recorded when:</p> <ul> <li>A user taps on a row item to open a Story</li> <li>A Story is loaded because the previous Story finished</li> <li>A Story is loaded because the user skipped the last Page of the previous Story</li> <li>A user swipes left to the next Story</li> <li>A user swipes right to the previous Story</li> <li>A user is sent directly to a Story by a deep link</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Opened Reason <code>openedReason</code> The action which the user took to open the Story. OpenedReason Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Read Status <code>storyReadStatus</code> Whether the Story was read or unread at the point it was opened. <code>read</code>, <code>unread</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#dismissed-story-dismissedstory","title":"Dismissed Story (<code>dismissedStory</code>)","text":"<p>The <code>dismissedStory</code> event is recorded when:</p> <ul> <li>A user taps close to dismiss the Story</li> <li>A user taps to skip the last Page of the final Story to dismiss the Story and go back to the page they were on previously</li> <li>A user swipes left on the final Story to dismiss the Story</li> <li>A user swipes right on the first Story to dismiss the Story</li> <li>A user completes the final Page of the final Story and the Story view is dismissed</li> <li>The player closes for another DismissedReason, such as the browser back button or the <code>Esc</code> key</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Dismissed Reason <code>dismissedReason</code> The reason the Story was dismissed. DismissedReason Duration Viewed <code>durationViewed</code> In milliseconds, how long the user viewed Stories, measured from the most recent <code>openedStory</code> event with an <code>openedReason</code> of <code>storyListTap</code> or <code>deepLink</code>. The timer resets after each <code>dismissedStory</code> event. 1200, 1312, 29 Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Pages Viewed <code>pagesViewed</code> The total number of Pages the user has viewed since the most recent <code>openedStory</code> event with an <code>openedReason</code> of <code>storyListTap</code> or <code>deepLink</code>. The count resets after each <code>dismissedStory</code> event. 1, 2, 3, 4 Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#skipped-story-skippedstory","title":"Skipped Story (<code>skippedStory</code>)","text":"<p>The <code>skippedStory</code> event is recorded when:</p> <ul> <li>A user swipes left to the next Story before completing the current Story</li> <li>A user skips the last Page of a Story</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#completed-story-completedstory","title":"Completed Story (<code>completedStory</code>)","text":"<p>The <code>completedStory</code> event is recorded when the final Page in a Story is opened. The <code>openedPage</code> event is recorded at the same time.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#opened-page-openedpage","title":"Opened Page (<code>openedPage</code>)","text":"<p>The <code>openedPage</code> event is recorded when a user first opens a Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Content Length <code>contentLength</code> In seconds, the total duration of the Page content. 15, 41, 32 Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Opened Reason <code>openedReason</code> The action which the user took to open the Page. OpenedReason Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#action-button-tapped-actionbuttontapped","title":"Action Button Tapped (<code>actionButtonTapped</code>)","text":"<p>The <code>actionButtonTapped</code> event is recorded when:</p> <ul> <li>A user swipes up on a Page to open a link</li> <li>A user taps on the swipe up element of a Page to open a link</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#share-button-tapped-sharebuttontapped","title":"Share Button Tapped (<code>shareButtonTapped</code>)","text":"<p>The <code>shareButtonTapped</code> event is recorded when a user taps the share button on a Page.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#share-success-sharesuccess","title":"Share Success (<code>shareSuccess</code>)","text":"<p>The <code>shareSuccess</code> event is recorded when a user finishes sharing a Page. This happens when the promise returned by your <code>onShareButtonTapped</code> callback resolves, when the browser share sheet completes, or when the Page media finishes downloading.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Share Method <code>shareMethod</code> How the Page was shared: as a link (<code>shareLink</code>) or as its media (<code>shareMedia</code> or <code>share</code>). <code>shareLink</code>, <code>shareMedia</code>, <code>share</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#previous-page-previouspage","title":"Previous Page (<code>previousPage</code>)","text":"<p>The <code>previousPage</code> event is recorded when a user taps back to go to a previous Page in the Story.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#previous-story-previousstory","title":"Previous Story (<code>previousStory</code>)","text":"<p>The <code>previousStory</code> event is recorded when:</p> <ul> <li>A user swipes right to go to the previous Story (unless this is the first Story, in which case <code>dismissedStory</code> is recorded instead)</li> <li>A user taps back on the first Page in a Story (and this is not the first Page in the first Story)</li> </ul> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#completed-page-completedpage","title":"Completed Page (<code>completedPage</code>)","text":"<p>The <code>completedPage</code> event is recorded when a Page finishes and the player moves on to the next Page or Story automatically. The event describes the Page that finished.</p> <p><code>ActivityType</code> lists this event as deprecated, but the SDK still sends it. Avoid building new reports on it.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Content Length <code>contentLength</code> In seconds, the total duration of the Page content. 15, 41, 32 Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"analytics/StoryEvents/#skipped-page-skippedpage","title":"Skipped Page (<code>skippedPage</code>)","text":"<p>The <code>skippedPage</code> event is recorded when a user taps or swipes forward to leave a Page before it finishes. The event describes the Page the user left.</p> <p><code>ActivityType</code> lists this event as deprecated, but the SDK still sends it. Avoid building new reports on it.</p> <p>This event contains the following properties:</p> Event Property Property Name Description Sample values Captions Enabled <code>captionsEnabled</code> Whether captions were on when the event occurred. <code>true</code>, <code>false</code> Categories <code>categories</code> A list of the category names assigned to the Story for which the event occurred. [\"Top Stories\", \"Europe\", \"Recap\"] Category Details <code>categoryDetails</code> A list of Category Detail objects assigned to the Story for which the event occurred. <code>[{ name: 'Greens v Blues, 10/06/2022', id: '0012200025', externalId: 'game-0012200025', type: 'game', placement: 'Game Screen' }]</code> Current Category <code>currentCategory</code> The Category for the Story with which the user is interacting. This event property includes the Category's name (<code>title</code>), external ID (<code>id</code>), and placement. <code>{ title: 'Greens v Blues, 10/06/2022', id: 'game-0012200025', placement: 'Game Screen' }</code> Page Action Text <code>pageActionText</code> If the Page associated with the event has an Action, this property captures its associated \u2018Call To Action\u2019 text. \u201cSwipe Up\u201d, \u201cGet Started\u201d Page Action URL <code>pageActionUrl</code> If the Page associated with the event has an Action, the URL to which the Action links. <code>https://example.com/action</code> Page Has Action <code>pageHasAction</code> Whether the Page associated with the event contains an Action. <code>true</code>, <code>false</code> Page ID <code>pageId</code> The ID of the Page for which the event occurred. <code>cce4f2c3-c6f2-4a0a-9d8c-b52e4080e658</code> Page Index <code>pageIndex</code> The index of the Page in the Story for which the event occurred. Ads do not affect this index. This property uses 1-based indexing. 1, 2, 3, \u2026 Page Title <code>pageTitle</code> The title of the Page for which the event occurred. \u201cStats page\u201d, \u201cBest Fit\u201d Page Type <code>pageType</code> The type of Page associated with the event. <code>image</code>, <code>video</code>, <code>poll</code>, <code>triviaQuiz</code> Story ID <code>storyId</code> The ID of the Story for which the event occurred. <code>3241dbc1-ae7b-4b55-a236-1294f18e2584</code> Story Index <code>storyIndex</code> 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 property uses 1-based indexing. 1, 2, 3, \u2026 Story Page Count <code>storyPageCount</code> The number of Pages in the Story. 1, 2, 3, \u2026 Story Playback Mode <code>storyPlaybackMode</code> Whether the Story was opened with a <code>Storyteller.sharedInstance.open*</code> method or its URL (<code>singleStory</code>), or by the user tapping it in a row or grid (<code>list</code>). <code>list</code>, <code>singleStory</code> Story Title <code>storyTitle</code> The title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d Story Display Title <code>storyDisplayTitle</code> The long display title of the Story for which the event occurred. \u201cTonight\u2019s Movies\u201d, \u201cQuote of the Day\u201d"},{"location":"delegates/","title":"Handle delegates and callbacks","text":"<p>A delegate is an object of callback functions that the SDK calls when something happens. Storyteller has one global delegate, and each view has its own delegate. Every callback is optional.</p>"},{"location":"delegates/#delegate-types","title":"Delegate types","text":"What you want to handle TypeScript type Where you set it Guide Analytics events, share taps, ad requests, and in-app action links from every Story and Clips player <code>IStorytellerDelegate</code> <code>Storyteller.sharedInstance.delegate</code> Handle global callbacks Loading and player dismissal for one row or grid <code>IListViewDelegate</code> The row or grid's <code>delegate</code> property Handle view callbacks Loading, dismissal, and the back button for one Clips player view <code>IStorytellerClipsPlayerDelegate</code> The <code>delegate</code> property of a <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code> Handle view callbacks <p>Set the global delegate before you call <code>initialize</code>, so that it receives the <code>sdkInitialized</code> event. Assigning a delegate replaces the previous one: callbacks you leave out of the new object stop being called.</p>"},{"location":"delegates/#guides","title":"Guides","text":"<ul> <li>Handle global callbacks</li> <li>Handle view callbacks</li> <li>Integrate analytics</li> <li>Integrate ads</li> <li>API reference</li> </ul>"},{"location":"getting-started/","title":"Before you start","text":"<p>Check what you need, then choose how to install the Web SDK. Use this page if you are adding Storyteller to a website for the first time.</p> <p>You need:</p> <ul> <li>A Storyteller API key. The key identifies your tenant: your organization's   Storyteller account and its content. Ask your Storyteller contact for a key,   or get in touch.</li> <li>Published content in the same tenant: at least one Story, or a Clips   collection with published Clips.</li> <li>An element on your page, such as a <code>&lt;div&gt;</code>, where the SDK can render a view.</li> <li>To open the linked code examples, a GitHub account with   access to the Storyteller Web Showcase source.</li> </ul> <p>The examples use these placeholders. Replace them with your own values:</p> <ul> <li><code>demo-api-key</code>: your API key</li> <li><code>your-user-id</code>: the ID your site uses for the signed-in user</li> <li><code>category-id</code>: the ID of a Story Category</li> <li><code>collection-id</code>: the ID of a Clips collection</li> </ul>"},{"location":"getting-started/#choose-an-installation-path","title":"Choose an installation path","text":"<p>Choose the guide that matches how your site builds its JavaScript:</p> <ul> <li>Install with a script tag: your site has no JavaScript build   step, so the SDK loads from the Storyteller CDN</li> <li>Install from npm: a bundler, such as webpack or Vite, builds your   JavaScript</li> <li>Use React or Next.js: a React component renders the   Storyteller container</li> </ul>"},{"location":"getting-started/#showcase-source-access","title":"Access the Storyteller Web Showcase source","text":"<p>The Storyteller Web Showcase is a Next.js app that uses the Web SDK. Many guides link to its source code on GitHub. The repository is private.</p> <p>To open the Showcase links:</p> <ol> <li>Tell your Storyteller contact which GitHub account you want to use, and ask    them to give that account access.</li> <li>Accept the GitHub invitation.</li> <li>Sign in to GitHub with that account before you open a link.</li> </ol> <p>Until your account has access, Showcase links return a 404 error. If a link still returns 404, check that you accepted the invitation and that you are signed in with the account that has access. If you still can't open the source, contact support@getstoryteller.com.</p> <p>Resources</p> <ul> <li>Storyteller Web Showcase repository</li> <li>Storyteller Web Showcase README</li> </ul> <p> </p>"},{"location":"getting-started/#next-steps","title":"Next steps","text":"<ul> <li>Show your first Story row</li> <li>Choose a view</li> <li>Identify and personalize users</li> <li>Control privacy and tracking</li> <li>Customize themes</li> <li>Handle delegates and callbacks</li> </ul>"},{"location":"getting-started/migrate-to-11/","title":"Migrate from version 10 to 11","text":"<p>Use this guide to update a Web SDK 10.13.x integration to 11.0.0. Version 11 keeps the 10.13 entry points, so most integration code does not change. It also has breaking changes. Read Breaking changes and make the changes that apply to you before you deploy version 11.</p>"},{"location":"getting-started/migrate-to-11/#record-the-current-integration","title":"Before you update","text":"<p>Record the current integration, so you can test the update and roll it back:</p> <ul> <li>the current SDK version</li> <li>the installation path: npm or script tag</li> <li>where the SDK files are hosted, if you host them yourself</li> <li><code>initialize</code> options and how you set and change users</li> <li>each view constructor and its configuration</li> <li>privacy, analytics, callback, and ad settings</li> <li>any proxy, allowlist, or Content Security Policy between the browser and   Storyteller</li> </ul> <p>Read the current version from the SDK.</p> <pre><code>console.log(Storyteller.sharedInstance.version);\n</code></pre>"},{"location":"getting-started/migrate-to-11/#keep-the-public-entry-points","title":"What stays the same","text":"<p>Version 11 keeps these entry points:</p> <ul> <li>the <code>@getstoryteller/storyteller-sdk-javascript</code> package name</li> <li>the <code>Storyteller</code> browser global</li> <li><code>Storyteller.sharedInstance.initialize</code></li> <li>the Story and Clip view constructor names</li> <li>the npm stylesheet, <code>dist/storyteller.min.css</code></li> </ul> <p>Namespace and named imports keep working, and the package includes TypeScript declarations.</p>"},{"location":"getting-started/migrate-to-11/#breaking-changes","title":"Breaking changes","text":"<p>Each change below says what to do. Some changes apply only to certain integrations, such as self-hosted SDK files or TypeScript code.</p>"},{"location":"getting-started/migrate-to-11/#viewing-history-loads-from-storyteller","title":"Viewing history loads from Storyteller","text":"<p>When <code>enableFunctionalCookies</code> and <code>enableRemoteViewingStore</code> are <code>true</code> (the defaults), <code>initialize</code> requests the current user's viewing history from Storyteller and waits for it. The history covers read Pages, Clip likes and views, and Poll and Quiz answers. History for an <code>externalId</code> follows the user across browsers and devices.</p> <p>Read state from 10.13 carries over. With the default privacy options, 10.13 sent each opened Page, Poll vote, Quiz answer, and Clip like to Storyteller under the user ID stored in <code>Storyteller.user</code>. Version 11 keeps that user ID and loads the same history, so Stories that users read in 10.13 still show as read. Read state does not carry over when 10.13 ran with <code>enableFunctionalCookies: false</code> or <code>enableRemoteViewingStore: false</code>; see Local storage keys changed.</p> <p><code>enablePersonalization: false</code> does not stop this request. The request sends the user ID but no user attributes, as 10.13 activity events already did.</p> <p>If this request fails, <code>initialize</code> rejects with <code>InvalidApiKeyError</code>, <code>NetworkError</code>, or <code>NetworkTimeoutError</code>, and the SDK does not send the <code>sdkInitialized</code> event.</p> <p>To update:</p> <ol> <li>Keep a <code>catch</code> on every <code>initialize</code> call. See    Handle initialization errors.</li> <li>If a proxy, firewall, or allowlist sits between the browser and the    Storyteller API, allow the requests in the table below.</li> <li>If your proxy answers CORS preflight requests, add    <code>x-storyteller-recent-viewed-clip-ids</code> to its <code>Access-Control-Allow-Headers</code>    response.</li> </ol> Request Path or header Viewing history <code>GET /api/UserActivity/*</code> Clips pages <code>GET /api/app/clips/{collection}/clips/paged/fresh</code> Recently viewed Clips <code>x-storyteller-recent-viewed-clip-ids</code> header on Clips requests <p>See Remote viewing store for the privacy options that control this request.</p>"},{"location":"getting-started/migrate-to-11/#local-storage-keys-changed","title":"Local storage keys changed","text":"<p>Version 11 uses new local storage keys for viewing history. It does not read the 10.13 keys and does not remove them.</p> 10.13 key 11.0 key <code>Storyteller.clipLikes</code> <code>Storyteller.likes</code> <code>Storyteller.clipsViewed</code> <code>Storyteller.viewedClips</code> <code>Storyteller.pollAnswerMap</code> <code>Storyteller.pollAnswers</code> <code>Storyteller.quizAnswerMap</code> <code>Storyteller.triviaQuizAnswers</code> <code>Storyteller.storiesReadMap</code> <code>Storyteller.readPages</code> <p>With the default <code>enableRemoteViewingStore: true</code>, the SDK keeps viewing history in Storyteller, not in local storage. With <code>enableRemoteViewingStore: false</code>, the SDK keeps viewing history only in the new local storage keys. Read Pages, likes, and answers that 10.13 saved do not carry over, so Stories that users read in 10.13 show as unread.</p> <p>To update:</p> <ol> <li>Replace the 10.13 key names in your cookie or consent inventory. The    local storage table    lists every current key.</li> <li>If your consent policy requires it, remove the five 10.13 keys yourself.</li> </ol>"},{"location":"getting-started/migrate-to-11/#the-script-build-loads-files-from-its-directory","title":"The script build loads files from its directory","text":"<p>The script build now downloads Story player, Clips player, Poll, Quiz, and caption code as separate files the first time a page needs them. It loads them from the directory that served <code>storyteller.min.js</code>. The Storyteller CDN serves every file. The npm package is not affected.</p> <p>If you host the SDK files yourself:</p> <ol> <li>Copy every file in the version's <code>dist</code> directory to one directory on your    server.</li> <li>Keep the file names.</li> <li>Load <code>storyteller.min.js</code> from its own <code>&lt;script&gt;</code> tag. Do not rename,    bundle, or inline it.</li> </ol> <p>If your page has a Content Security Policy, its <code>script-src</code> must allow the directory that serves the SDK files, on the CDN or on your server. A policy that allows only a nonce or a hash for the main script also needs <code>'strict-dynamic'</code> or the SDK host.</p> <p>See Host the SDK files.</p>"},{"location":"getting-started/migrate-to-11/#npm-peer-dependencies-and-entry-points","title":"npm peer dependencies and entry points","text":"<p>The npm package now declares these peer dependencies, because its TypeScript declarations import them:</p> <ul> <li><code>@types/react</code>: <code>&gt;=17 &lt;20</code></li> <li><code>@types/react-router-dom</code>: <code>^5.1.7</code></li> </ul> <p>npm 7 and later installs them. If <code>npm install</code> reports a peer dependency conflict, change your <code>@types/react</code> version to one in that range. See TypeScript declarations.</p> <p>The package also adds <code>import</code> and <code>require</code> entry points and publishes its declarations at <code>dist/index.npm.d.ts</code>. It no longer ships <code>index.js</code>, <code>types/*.d.ts</code>, or SDK source files. Import only these paths:</p> <ul> <li><code>@getstoryteller/storyteller-sdk-javascript</code></li> <li><code>@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css</code></li> </ul> <p>A default import resolves only in ES module builds. In CommonJS builds, including Jest, use <code>import * as Storyteller</code> or <code>require</code>. Version 10.13 behaved the same way.</p>"},{"location":"getting-started/migrate-to-11/#global-and-typescript-changes","title":"Global and TypeScript changes","text":"<ul> <li>The SDK no longer installs the <code>reflect-metadata</code> polyfill on the page's   global <code>Reflect</code> object. If your code calls <code>Reflect.getMetadata</code> or   <code>Reflect.defineMetadata</code>, import <code>reflect-metadata</code> in your application.</li> <li><code>ActivityType</code> has a new <code>sdkInitialized</code>   member. Update exhaustive <code>switch</code> statements over <code>ActivityType</code>.</li> <li><code>Story</code> has new <code>pinnedChipText</code> and <code>customLiveChipText</code> properties. Add   them to typed test data.</li> <li>The undocumented <code>QuizRenderer.clearQuizData()</code> method was removed. Remove   any calls to it.</li> </ul>"},{"location":"getting-started/migrate-to-11/#review-version-11-behavior","title":"Behavior changes","text":"<p>These changes need no code, but check them in your application:</p> <ul> <li>Player code loads on demand (script tag only): the script build   downloads Story player, Clips player, Poll, Quiz, and caption code the first   time a page needs it. The npm package still includes this code, and your   bundler decides how it loads.</li> <li>AMP player preload: each Stories row or grid starts a low-priority   download of the AMP player script before the first Story opens. Set   <code>preload</code> to <code>true</code> to prepare more of   the Story player in advance.</li> <li>Story ordering: when the Stories API uses   started-aware ordering, rows   and grids show Stories the user has not opened, then Stories in progress,   then finished Stories. Pinned and Live Stories keep their priority.</li> <li>Clips paging: Clips rows, grids, and players that show a Collection   load more Clips as the user   reaches the last loaded Clip. The   <code>onDataLoadComplete</code> callback reports   the number of Clips in the first page as <code>dataCount</code>. Later pages load   without delegate callbacks.</li> <li>Clip details: the Clips player can show a   long description in an expandable   details area.</li> <li>Story chips: Story tiles can show   custom Live and pinned chip text   from Story content.</li> <li>Compact Clip action buttons: if your remote theme sets   <code>clipsActionButtonCompactSize</code>,   the Clips player shows smaller action buttons.</li> <li>Like and share counts: if your remote theme sets   <code>showLikeCount</code> or <code>showShareCount</code> to <code>false</code>,   the Clips player hides that count.</li> <li>Caption defaults: each caption theme   field set for a feed now overrides only that field of the tenant caption   theme. Default captions use 16 px text, the font's natural line height, and   a <code>#171A25</code> background instead of 18 px text, a 22 px line height, and a   <code>#000000</code> background.</li> <li>Stories with no Pages: rows and grids no longer show them.</li> <li><code>sdkInitialized</code> event: <code>onUserActivityOccurred</code> receives   <code>sdkInitialized</code> during <code>initialize</code>.   If your handler maps every event type, make it ignore or record this one.</li> </ul>"},{"location":"getting-started/migrate-to-11/#update-an-npm-integration","title":"Update an npm integration","text":"<p>Install version 11.0.0.</p> <pre><code>npm install @getstoryteller/storyteller-sdk-javascript@11.0.0\n</code></pre> <p>If npm reports a peer dependency conflict, see npm peer dependencies and entry points.</p> <p>Keep the SDK and stylesheet imports together.</p> <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport '@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css';\n</code></pre>"},{"location":"getting-started/migrate-to-11/#update-a-script-integration","title":"Update a script integration","text":"<p>Change the version segment in the CDN URL.</p> <pre><code>&lt;script src=\"https://content.usestoryteller.com/javascript-sdk/11.0.0/dist/storyteller.min.js\"&gt;&lt;/script&gt;\n</code></pre> <p>Use the fixed URL in production. This keeps later releases from changing the SDK without an application deployment.</p> <p>Earlier guides showed a <code>/javascript-sdk/latest/</code> URL. That path does not serve production releases. Replace it with a fixed version URL, such as the one above.</p> <p>If you host the SDK files yourself, copy every file in the 11.0.0 <code>dist</code> directory. See The script build loads files from its directory.</p>"},{"location":"getting-started/migrate-to-11/#test-the-update","title":"Test the update","text":"<p>Check these paths with version 11.0.0:</p> <ol> <li>Initialize the SDK with a test tenant. Check that <code>initialize</code> resolves.    With the default privacy options, also check that the viewing-history    request succeeds in the browser's network panel.</li> <li>Load every row, grid, and embedded player your application uses. Check    Story ordering and later Clips pages where your tenant enables them.</li> <li>Open and close Story and Clips players. Check long Clip descriptions,    custom Story chips, compact Clip action buttons, like and share counts,    captions, and long Poll and Quiz answers where you use them.</li> <li>Read a Story, reload the page, and check that the Story still shows as    read. Repeat the check after you change between anonymous and signed-in    users, if your application supports both.</li> <li>If you host the SDK files, open a Story, a Clips player, a Poll, and a    Quiz. Check that each player, Poll, Quiz, and caption file loads from your    server with no <code>404</code> errors.</li> <li>Open each player and check the browser console for Content Security Policy    errors.</li> <li>Confirm privacy settings, analytics callbacks, and ad requests. Check the    <code>sdkInitialized</code> event if your application handles activity events.</li> <li>Change routes in a single-page application. Check that your code calls    <code>destroy()</code> before it removes a view's    container, and that a new view appears when the route returns.</li> </ol> <p>Review the release notes for other changes that apply to your integration.</p>"},{"location":"getting-started/migrate-to-11/#roll-back-a-test-deployment","title":"Roll back","text":"<p>Restore the previous fixed npm version or CDN URL, then rebuild and deploy the application. If you host the SDK files, restore the 10.13 files too. Keep the previous version number in the release record until the version 11 checks pass.</p> <p>Version 10.13 does not read the local storage keys that version 11 uses.</p>"},{"location":"getting-started/migrate-to-11/#get-help","title":"Get help","text":"<p>If the update fails, work through Troubleshoot an integration. If you still need help, contact Storyteller Support.</p>"},{"location":"getting-started/npm/","title":"Install from npm","text":"<p>Use the npm package when a bundler, such as webpack or Vite, builds your application's JavaScript. The package is <code>@getstoryteller/storyteller-sdk-javascript</code>.</p>"},{"location":"getting-started/npm/#install-the-package","title":"Install the package","text":"<pre><code>npm install @getstoryteller/storyteller-sdk-javascript\n</code></pre>"},{"location":"getting-started/npm/#typescript-declarations","title":"TypeScript declarations","text":"<p>The package includes TypeScript declarations. They import types from React and React Router, so the package declares these peer dependencies:</p> <ul> <li><code>@types/react</code> <code>&gt;=17 &lt;20</code></li> <li><code>@types/react-router-dom</code> <code>^5.1.7</code></li> </ul> <p>npm 7 and later installs peer dependencies for you. If <code>npm install</code> reports a peer dependency conflict, use an <code>@types/react</code> version in that range. The API reference lists the exported types.</p>"},{"location":"getting-started/npm/#import-the-sdk-and-styles","title":"Import the SDK and styles","text":"<p>Import both files from code that runs in the browser.</p> <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport '@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css';\n</code></pre> <p>The stylesheet ships in the npm package. Configure your bundler to handle CSS imports.</p> <p>Import only these two paths: the package root and <code>@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css</code>. Version 11 no longer ships <code>index.js</code>, <code>types/*.d.ts</code>, or SDK source files, so other paths fail.</p> <p>A default import (<code>import Storyteller from '@getstoryteller/storyteller-sdk-javascript'</code>) works only in ES module builds. In CommonJS builds, including Jest, use <code>import * as Storyteller</code>.</p> <p>The npm package includes the Story player, Clips player, Poll, Quiz, and caption code in its single JavaScript file. Your bundler decides how that code loads. The script-tag build downloads the same code on demand instead.</p>"},{"location":"getting-started/npm/#commonjs-browser-bundles","title":"CommonJS browser bundles","text":"<p>The package also supports <code>require</code> in browser code built with CommonJS:</p> <pre><code>const Storyteller = require('@getstoryteller/storyteller-sdk-javascript');\nrequire('@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css');\n</code></pre> <p>Your bundler needs a CSS loader for the stylesheet <code>require</code>. Node.js can <code>require</code> or <code>import</code> the JavaScript entry, for example during server rendering, but views work only in the browser. Load the stylesheet only through your browser build.</p> <p>The Storyteller Web Showcase keeps its <code>PackagedStoryteller</code> import and stylesheet import in one browser-only module.</p>"},{"location":"getting-started/npm/#initialize-the-sdk","title":"Initialize the SDK","text":"<pre><code>await Storyteller.sharedInstance.initialize('demo-api-key');\n</code></pre> <p>Call <code>initialize</code> and wait for it to resolve before you create a Storyteller view. Replace <code>demo-api-key</code> with your API key. Top-level <code>await</code> works only in ES modules. Otherwise, call <code>initialize</code> inside an <code>async</code> function, as shown in Handle initialization errors.</p>"},{"location":"getting-started/npm/#add-a-story-row","title":"Add a Story row","text":"<pre><code>&lt;div id=\"storyteller-stories-row\" style=\"height: 200px\"&gt;&lt;/div&gt;\n</code></pre> <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView(\n  'storyteller-stories-row'\n);\n</code></pre> <p>Call <code>storyRow.destroy()</code> before your application removes or replaces the container.</p>"},{"location":"getting-started/npm/#next-steps","title":"Next steps","text":"<ul> <li>Show your first Story row</li> <li>Use React or Next.js</li> <li>Configure views</li> </ul>"},{"location":"getting-started/react-nextjs/","title":"Use React or Next.js","text":"<p>Use this guide to show a Storyteller view in a React or Next.js app. Initialize the SDK once for the page, create the view after the component mounts, and destroy the view when the component unmounts.</p> <p>Install the SDK with npm first.</p>"},{"location":"getting-started/react-nextjs/#initialize-the-sdk-once","title":"Initialize the SDK once","text":"<p>Add a module that calls <code>initialize</code> once and shares its promise with every component:</p> <pre><code>// storyteller.js\nimport * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\n\nlet initialization;\n\nexport function startStoryteller() {\n  if (!initialization) {\n    initialization = Storyteller.sharedInstance\n      .initialize('demo-api-key')\n      .catch((error) =&gt; {\n        initialization = undefined;\n        throw error;\n      });\n  }\n\n  return initialization;\n}\n</code></pre> <p>The first call starts <code>initialize</code>. Later calls return the same promise. If <code>initialize</code> fails, the helper clears the cached promise, so the next call tries again.</p> <p>Each <code>initialize</code> call resets the global theme (<code>Storyteller.sharedInstance.theme</code>) to the defaults. If you use a global theme, set it after <code>initialize</code> resolves, for example in a <code>.then()</code> inside <code>startStoryteller()</code>. A theme set in a view's <code>configuration</code> is kept. See Customize themes.</p> <p>When the signed-in user changes, call <code>initialize</code> again as described in Identify and personalize users, then set the global theme again.</p>"},{"location":"getting-started/react-nextjs/#react","title":"React","text":"<p>Import the SDK, its stylesheet, and the helper:</p> <pre><code>import { useEffect } from 'react';\nimport * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport '@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css';\nimport { startStoryteller } from './storyteller';\n</code></pre> <p>Create the view after <code>startStoryteller()</code> resolves, and destroy it in the effect cleanup:</p> <pre><code>export function StoryRow() {\n  useEffect(() =&gt; {\n    let isMounted = true;\n    let storyRow;\n\n    startStoryteller()\n      .then(() =&gt; {\n        if (isMounted) {\n          storyRow = new Storyteller.StorytellerStoriesRowView(\n            'storyteller-stories-row'\n          );\n        }\n      })\n      .catch((error) =&gt; console.error('Storyteller could not start.', error));\n\n    return () =&gt; {\n      isMounted = false;\n      storyRow?.destroy();\n    };\n  }, []);\n\n  return &lt;div id=\"storyteller-stories-row\" style={{ height: 200 }} /&gt;;\n}\n</code></pre> <p>In development, React Strict Mode runs each effect, its cleanup, and the effect again. The cleanup sets <code>isMounted</code> to <code>false</code>, so only the second effect creates a view. Both effects get the same promise from <code>startStoryteller()</code>, so the SDK initializes once.</p> <p>Each view needs a container ID that is unique on the page. If you render the component more than once at the same time, pass a different ID to each instance. The ID must follow the container ID rules.</p>"},{"location":"getting-started/react-nextjs/#nextjs-app-router","title":"Next.js App Router","text":"<p>Import the stylesheet in <code>app/layout.js</code>.</p> <pre><code>import '@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css';\n</code></pre> <p>Keep the view in a Client Component so the SDK runs in the browser. Add <code>'use client'</code> at the top of the component file, then use the same <code>StoryRow</code> component as in the React section:</p> <pre><code>'use client';\n\nimport { useEffect } from 'react';\nimport * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\nimport { startStoryteller } from './storyteller';\n</code></pre> <p>The Storyteller Web Showcase uses the same lifecycle. Its <code>isStorytellerInitialized</code> guard runs before view creation. Cleanup calls <code>view.destroy()</code>.</p>"},{"location":"getting-started/react-nextjs/#next-steps","title":"Next steps","text":"<ul> <li>Add a Story or Clips row</li> <li>Identify and personalize users</li> <li>Handle delegates and callbacks</li> </ul>"},{"location":"getting-started/script/","title":"Install with a script tag","text":"<p>Load the SDK from the Storyteller CDN when your site has no JavaScript build step.</p>"},{"location":"getting-started/script/#add-the-sdk","title":"Add the SDK","text":"<p>Add the versioned script before the closing <code>&lt;/body&gt;</code> tag, after the container, so the container exists when your code creates the view. A fixed version keeps the deployed SDK the same until you choose to update it.</p> <pre><code>&lt;div id=\"storyteller-stories-row\" style=\"height: 200px\"&gt;&lt;/div&gt;\n\n&lt;script src=\"https://content.usestoryteller.com/javascript-sdk/11.0.0/dist/storyteller.min.js\"&gt;&lt;/script&gt;\n&lt;script&gt;\n  async function startStoryteller() {\n    await Storyteller.sharedInstance.initialize('demo-api-key');\n\n    new Storyteller.StorytellerStoriesRowView(\n      'storyteller-stories-row'\n    );\n  }\n\n  startStoryteller().catch((error) =&gt; {\n    console.error('Storyteller could not start.', error);\n  });\n&lt;/script&gt;\n</code></pre> <p>The script adds its styles to the page. <code>Storyteller</code> becomes available on <code>window</code> after the script loads.</p> <p>Replace <code>demo-api-key</code> with your API key. To show Stories from specific Categories, pass their IDs as the second argument:</p> <pre><code>new Storyteller.StorytellerStoriesRowView('storyteller-stories-row', [\n  'category-id',\n]);\n</code></pre> <p>Note</p> <p>Earlier guides used a <code>/javascript-sdk/latest/</code> URL. That path does not serve production releases. Use a fixed version URL, such as the <code>11.0.0</code> URL above.</p>"},{"location":"getting-started/script/#host-the-sdk-files","title":"Host the SDK files","text":"<p>The script downloads the Story player, Clips player, Poll, Quiz, and caption code the first time a page needs it. These files load from the same directory as <code>storyteller.min.js</code>, for example <code>https://content.usestoryteller.com/javascript-sdk/11.0.0/dist/</code>. Their names look like <code>storyteller.story-player.&lt;hash&gt;.min.js</code>.</p> <p>The Storyteller CDN serves all of these files. To host the SDK on your own server:</p> <ul> <li>Copy every file in the version's <code>dist</code> directory to one directory.</li> <li>Keep the file names.</li> <li>Load <code>storyteller.min.js</code> from its own <code>&lt;script&gt;</code> tag. Don't bundle, rename,   or inline it.</li> </ul>"},{"location":"getting-started/script/#content-security-policy","title":"Content Security Policy","text":"<p>If your site uses a Content Security Policy (CSP), allow scripts from the SDK directory in <code>script-src</code>, for example <code>https://content.usestoryteller.com/javascript-sdk/11.0.0/dist/</code>. The SDK adds its files to the page as <code>&lt;script&gt;</code> elements without a nonce. If your policy allows scripts only by nonce or hash, also add <code>'strict-dynamic'</code> or the SDK directory.</p> <p>The Story player also loads the AMP Story player script from <code>https://stories.usestoryteller.com/amp/</code>.</p>"},{"location":"getting-started/script/#check-the-result","title":"Check the result","text":"<p>A horizontal row of Story tiles appears. If the container stays empty, open the browser console and look for a failed script request or an initialization error. See Troubleshoot an integration.</p> <p>The Storyteller Web Showcase builds the same versioned CDN URL in <code>buildVersionedDemoSdkScriptUrl</code>.</p>"},{"location":"getting-started/script/#next-steps","title":"Next steps","text":"<ul> <li>Show your first Story row</li> <li>Choose a view</li> <li>Identify and personalize users</li> </ul>"},{"location":"getting-started/troubleshooting/","title":"Troubleshoot an integration","text":"<p>Use this page when Storyteller doesn't appear, doesn't load, or doesn't behave as expected. Find the first step that fails, and fix it before you check later steps.</p>"},{"location":"getting-started/troubleshooting/#find-your-symptom","title":"Find your symptom","text":"What you see Start with <code>window.Storyteller</code> is <code>undefined</code>, or your build can't find the package 1. Confirm that the SDK loaded <code>initialize</code> rejects, or <code>isInitialized</code> stays <code>false</code> 2. Confirm initialization The row or grid stays empty 3. Check an empty row or grid Tiles appear, but a Story or Clip doesn't open or play 4. Check player requests A view breaks or appears twice after a route change 5. Check page transitions A callback or analytics event doesn't arrive 6. Check callbacks and analytics A theme change has no effect 7. Check themes Ads don't appear 8. Check ads"},{"location":"getting-started/troubleshooting/#1-confirm-that-the-sdk-loaded","title":"1. Confirm that the SDK loaded","text":"<p>For a script integration, open the browser Network panel and find <code>storyteller.min.js</code>. The request must return JavaScript with a successful HTTP status.</p> <p>Then check the browser global.</p> <pre><code>typeof window.Storyteller;\n</code></pre> <p>The result should be <code>\"object\"</code>.</p> <p>For an npm integration, check the build output for a missing package or CSS import. The application must include both imports from the npm installation guide.</p>"},{"location":"getting-started/troubleshooting/#2-confirm-initialization","title":"2. Confirm initialization","text":"<p>Call <code>enableLogging()</code> in your page code before you call <code>initialize</code>. The SDK then logs its warnings and request errors to the console.</p> <pre><code>Storyteller.sharedInstance.enableLogging();\nawait Storyteller.sharedInstance.initialize('demo-api-key');\n</code></pre> <p>Check the current state after the promise resolves.</p> <pre><code>console.log({\n  isInitialized: Storyteller.sharedInstance.isInitialized,\n  version: Storyteller.sharedInstance.version,\n});\n</code></pre> <p><code>isInitialized</code> should be <code>true</code>.</p> <p>If <code>initialize</code> rejects, check the start of <code>error.message</code>. The SDK doesn't export these error classes, and <code>error.name</code> is always <code>\"Error\"</code>.</p> Error message starts with Check <code>InvalidApiKeyError</code> A request returned HTTP 401 or 404. Confirm that the key belongs to the intended Storyteller tenant. <code>NetworkError</code> Inspect the settings request and the viewing-history request (<code>GET /api/UserActivity/{userId}</code>), their HTTP status, and the response body. Confirm that the settings response contains settings. <code>NetworkTimeoutError</code> Check the network path, proxy, firewall, and request timeout. <p>With the default privacy options, <code>initialize</code> requests the user's viewing history from Storyteller and waits for it. If a proxy or allowlist sits between the browser and the Storyteller API, allow that request.</p> <p>If the promise rejects with a text message instead of an <code>Error</code>, <code>initialize</code> was called without an API key.</p>"},{"location":"getting-started/troubleshooting/#3-check-an-empty-row-or-grid","title":"3. Check an empty row or grid","text":"<p>Confirm each item:</p> <ul> <li>The container exists before you create the view.</li> <li>Its ID is unique on the page.</li> <li>The constructor receives the same ID.</li> <li>The tenant has published content for the supplied Category or collection.</li> <li>Page CSS does not hide the container or set its width to zero.</li> </ul> <p>Set a delegate with an <code>onDataLoadComplete</code> callback, as shown in Check the result. If <code>success</code> is <code>false</code> and <code>error.message</code> starts with <code>EmptyResponseError</code>, the request worked but returned no Stories or Clips.</p> <p>Remove optional Category IDs from a Story view to check the default Home list. Confirm that the Story is published in that list.</p> <pre><code>new Storyteller.StorytellerStoriesRowView('storyteller-stories-row');\n</code></pre> <p>If the row appears but its tiles have the wrong size, set a height on the row container. Without one, the SDK uses a default tile height.</p>"},{"location":"getting-started/troubleshooting/#4-check-player-requests","title":"4. Check player requests","text":"<p>Open a Story or Clip and inspect failed Network requests.</p> <p>The script build downloads the Story player, Clips player, Poll, Quiz, and caption files the first time a page needs them. These files load from the directory that served <code>storyteller.min.js</code>, and their names start with <code>storyteller.</code>, such as <code>storyteller.story-player.&lt;hash&gt;.min.js</code>. Check these causes:</p> <ul> <li>A file returns 404: if you host the SDK yourself, copy every file in the   version's <code>dist</code> directory and keep the file names. See   Host the SDK files.</li> <li>The console reports a Content Security Policy violation: allow scripts from   the SDK directory. See   Content Security Policy.</li> <li>A proxy or ad blocker blocks a file.</li> </ul> <p>The npm build includes this code in its own JavaScript file, so these requests don't appear.</p> <p>Record the first failed request and its HTTP status. Remove API keys, user IDs, and private query values before you share the request.</p>"},{"location":"getting-started/troubleshooting/#5-check-page-transitions","title":"5. Check page transitions","text":"<p>Destroy each view before a single-page application removes its container.</p> <pre><code>storyRow.destroy();\n</code></pre> <p>Destroy the old view before you create a new one in the same container. Two views on the page at the same time need different container IDs. Initialize the SDK once for the page, as shown in Use React or Next.js.</p>"},{"location":"getting-started/troubleshooting/#6-check-callbacks-and-analytics","title":"6. Check callbacks and analytics","text":"<p>Check the global delegate (<code>IStorytellerDelegate</code>):</p> <ul> <li>Set <code>Storyteller.sharedInstance.delegate</code> before you call <code>initialize</code>. The   <code>sdkInitialized</code> event is sent during <code>initialize</code>.</li> <li>Each assignment replaces all four global callbacks: <code>onUserActivityOccurred</code>,   <code>onShareButtonTapped</code>, <code>getAdConfig</code>, and <code>userNavigatedToApp</code>. A callback   you leave out stops working. Define all callbacks in one object, or spread   the current delegate.</li> <li><code>onUserActivityOccurred</code> receives events only when <code>enableUserActivityTracking</code>   is <code>true</code>. Ad events also need <code>enableAdTracking</code>.</li> <li>Each <code>eventTrackingOptions</code> assignment replaces all options. An option you   leave out returns to its default.</li> </ul> <pre><code>Storyteller.sharedInstance.delegate = {\n  ...Storyteller.sharedInstance.delegate,\n  getAdConfig: () =&gt; ({ slot: '/1234/your-ad-unit' }),\n};\n</code></pre> <p>For a view delegate (<code>IListViewDelegate</code>), set <code>delegate</code> on the view object. A view starts loading while its constructor runs, so a delegate you assign after <code>new</code> doesn't receive the first <code>onDataLoadStarted</code> call. <code>onDataLoadComplete</code> still arrives.</p> <p>See Handle delegates and callbacks, Integrate analytics, and Control privacy and tracking.</p>"},{"location":"getting-started/troubleshooting/#7-check-themes","title":"7. Check themes","text":"<ul> <li>A theme in a view's <code>configuration</code> is merged over the global theme   (<code>Storyteller.sharedInstance.theme</code>) for that view only.</li> <li>Each <code>initialize</code> call resets the global theme to its defaults. Set the   global theme after <code>initialize</code> resolves, and set it again after a later   <code>initialize</code> call, such as a user change.</li> <li><code>uiStyle</code> selects the light or dark theme. With <code>auto</code>, the default, the view   follows the user's color scheme, so set both <code>theme.light</code> and <code>theme.dark</code>.</li> <li>Storyteller sets some values for your tenant or feed in the remote theme,   such as caption styling and   compact Clip action buttons.   Your JavaScript theme doesn't change them. Ask Storyteller to change them.</li> </ul> <p>Test one clearly visible property on a single view before you combine overrides. See Customize themes.</p>"},{"location":"getting-started/troubleshooting/#8-check-ads","title":"8. Check ads","text":"<p>Ask Storyteller which ad source your tenant uses. Storyteller First Party Ads need no code. For Google Ad Manager ads, check these items:</p> <ul> <li>The SDK calls <code>getAdConfig</code> on the global delegate. It must return an object   with a <code>slot</code> for both Story and Clip requests. <code>null</code> means no ad.</li> <li>Clip ad requests have no <code>story</code> field. They contain <code>clip</code>, <code>nextClip</code>, and   <code>collection</code>. A callback that reads <code>adRequestInfo.story</code> without a check   throws for Clips.</li> <li>The ad unit in <code>slot</code> must serve 1x1 ads.</li> <li>A later delegate assignment can remove <code>getAdConfig</code>. See   step 6.</li> <li>With <code>enableAdTracking: false</code>, ad requests don't include the current Story   or Clip, so line items that target them might not match.</li> </ul> <p>See Integrate ads.</p>"},{"location":"getting-started/troubleshooting/#contact-support","title":"Contact support","text":"<p>Send Storyteller Support this information:</p> <ul> <li>SDK version and installation method</li> <li>Browser name and version</li> <li>First error name and message</li> <li>First failed request and HTTP status</li> <li>Short steps that reproduce the issue</li> </ul> <p>Remove API keys, user IDs, tenant data, and ad-targeting values from logs and screenshots.</p>"},{"location":"reference/","title":"API reference","text":"<p>This reference lists the public API of Storyteller Web SDK 11.0.0. Each entry gives the TypeScript signature, parameters, defaults, errors, and the guide that shows the task. Use the guides to learn a workflow, and use these pages to check an exact name or type.</p>"},{"location":"reference/#reference-pages","title":"Reference pages","text":"<p>The reference has four pages, organized by the part of the SDK you call:</p> Page Covers Storyteller instance <code>Storyteller.sharedInstance</code> properties and methods, and <code>Storyteller.User</code> Views and configuration View constructors, view properties and methods, and the configuration interfaces Callbacks <code>IStorytellerDelegate</code>, <code>IListViewDelegate</code>, and <code>IStorytellerClipsPlayerDelegate</code> Types and enums Enums, event data, ad request data, theme classes, and server rendering"},{"location":"reference/#package-entry-points","title":"Package entry points","text":"<p>The SDK ships as an npm package and as a browser script on the Storyteller CDN. Both entry points expose the same singleton, view classes, and enums.</p>"},{"location":"reference/#npm-package","title":"npm package","text":"<p>Install the package from npm:</p> <pre><code>npm install @getstoryteller/storyteller-sdk-javascript\n</code></pre> <p>The package supports these import forms:</p> NamespaceNamedDefaultCommonJS <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\n</code></pre> <pre><code>import {\n  sharedInstance,\n  StorytellerStoriesRowView,\n} from '@getstoryteller/storyteller-sdk-javascript';\n</code></pre> <pre><code>import Storyteller from '@getstoryteller/storyteller-sdk-javascript';\n</code></pre> <pre><code>const Storyteller = require('@getstoryteller/storyteller-sdk-javascript');\n</code></pre> <p>The guides use the namespace import. The import forms return the same objects:</p> <ul> <li><code>Storyteller.sharedInstance</code> and the named <code>sharedInstance</code> export are the same instance</li> <li>The default export is the namespace object. The ESM entry (<code>index.mjs</code>) provides it</li> <li>The CommonJS entry (<code>index.cjs</code>) returns the namespace object itself, which has no <code>default</code> property</li> <li>Importing the package in Node.js does not require <code>window</code> or <code>document</code>, so server code can import it. Create views only in the browser</li> </ul> <p>The package <code>exports</code> map resolves these paths:</p> Import path Condition File <code>@getstoryteller/storyteller-sdk-javascript</code> <code>types</code> <code>dist/index.npm.d.ts</code> <code>@getstoryteller/storyteller-sdk-javascript</code> <code>import</code> <code>index.mjs</code> <code>@getstoryteller/storyteller-sdk-javascript</code> <code>require</code>, <code>default</code> <code>index.cjs</code> <code>@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css</code> none <code>dist/storyteller.min.css</code> <code>@getstoryteller/storyteller-sdk-javascript/package.json</code> none <code>package.json</code>"},{"location":"reference/#stylesheet","title":"Stylesheet","text":"<p>An npm integration must import the stylesheet once, from code that runs in the browser:</p> <pre><code>import '@getstoryteller/storyteller-sdk-javascript/dist/storyteller.min.css';\n</code></pre> <p>Your bundler must handle CSS imports. See Install from npm. In a Next.js App Router project, import the stylesheet in the root layout as shown in Use React or Next.js.</p>"},{"location":"reference/#cdn-script","title":"CDN script","text":"<p>Load a fixed SDK version from the Storyteller CDN:</p> <pre><code>&lt;script src=\"https://content.usestoryteller.com/javascript-sdk/11.0.0/dist/storyteller.min.js\"&gt;&lt;/script&gt;\n</code></pre> <p>The script defines the <code>Storyteller</code> global on <code>window</code>. It differs from the npm package in these ways:</p> <ul> <li>The script adds its styles to the page, so you do not need the npm stylesheet</li> <li>The script loads its Story player, Clips player, Poll, Quiz, and caption files from the directory that served <code>storyteller.min.js</code></li> <li><code>StorytellerTrackedFunctionalFeature</code> is a type-only export in this build, so <code>Storyteller.StorytellerTrackedFunctionalFeature</code> is <code>undefined</code>. Pass the string values instead, such as <code>'all'</code> or <code>'pageReadStatus'</code></li> </ul> <p>See Install with a script tag.</p>"},{"location":"reference/#typescript-declarations","title":"TypeScript declarations","text":"<p>The package <code>types</code> entry is <code>dist/index.npm.d.ts</code>. It re-exports every name from <code>dist/index.d.ts</code> and declares the default export.</p> <p>These exports are types only. Import them with <code>import type</code>, or reference them through the namespace, such as <code>Storyteller.IListConfiguration</code>:</p> <ul> <li><code>IListConfiguration</code>, <code>IStorytellerClipsPlayerConfiguration</code>, <code>IStorytellerEmbeddedClipsPlayerConfiguration</code></li> <li><code>IStorytellerDelegate</code>, <code>IListViewDelegate</code>, <code>IStorytellerClipsPlayerDelegate</code></li> <li><code>StorytellerEventTrackingOptions</code></li> <li><code>StorytellerAdRequestInfo</code>, <code>StorytellerStoriesAdRequestInfo</code>, <code>StorytellerClipsAdRequestInfo</code></li> <li><code>ServerRenderedStory</code>, <code>Subset</code></li> </ul> <p>Some parameter and return types are not exported by name, such as the <code>initialize</code> options and the <code>getAdConfig</code> return value. Derive them from an exported signature when you need a name:</p> <pre><code>import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\n\ntype UserInput = NonNullable&lt;\n  Parameters&lt;typeof Storyteller.sharedInstance.initialize&gt;[1]\n&gt;;\n\ntype GetAdConfig = NonNullable&lt;\n  Storyteller.IStorytellerDelegate['getAdConfig']\n&gt;;\ntype AdConfig = NonNullable&lt;ReturnType&lt;GetAdConfig&gt;&gt;;\n</code></pre> <p>The declarations import types from <code>react</code> and <code>react-router-dom</code>. The package lists <code>@types/react</code> (<code>&gt;=17 &lt;20</code>) and <code>@types/react-router-dom</code> (<code>^5.1.7</code>) as peer dependencies.</p>"},{"location":"reference/#exports","title":"Exports","text":"<p>The package exports these names. Names marked as types exist only in TypeScript.</p> Export Kind Reference <code>sharedInstance</code> Instance Storyteller instance <code>User</code> Instance <code>Storyteller.User</code> <code>StorytellerStoriesRowView</code> Class Views <code>StorytellerStoriesGridView</code> Class Views <code>StorytellerClipsRowView</code> Class Views <code>StorytellerClipsGridView</code> Class Views <code>StorytellerClipsPlayerView</code> Class Views <code>StorytellerEmbeddedClipsPlayerView</code> Class Views <code>RowView</code> Deprecated alias of <code>StorytellerStoriesRowView</code> Views <code>GridView</code> Deprecated alias of <code>StorytellerStoriesGridView</code> Views <code>IListConfiguration</code> Type Configuration <code>IStorytellerClipsPlayerConfiguration</code> Type Configuration <code>IStorytellerEmbeddedClipsPlayerConfiguration</code> Type Configuration <code>IStorytellerDelegate</code> Type Callbacks <code>IListViewDelegate</code> Type Callbacks <code>IStorytellerClipsPlayerDelegate</code> Type Callbacks <code>UiStyle</code> Enum Types <code>CellType</code> Enum Types <code>ActivityType</code> Enum Types <code>OpenedReason</code> Enum Types <code>DismissedReason</code> Enum Types <code>StorytellerTrackedFunctionalFeature</code> Enum (npm), type (CDN) Types <code>Alignment</code>, <code>ButtonAlignment</code>, <code>TextCase</code> Enum Types <code>StorytellerEventTrackingOptions</code> Type Types <code>UserActivityData</code> Class Types <code>ActivityEventDetail</code> Class Types <code>StorytellerAdRequestInfo</code> Type Types <code>StorytellerStoriesAdRequestInfo</code> Type Types <code>StorytellerClipsAdRequestInfo</code> Type Types <code>UiTheme</code> Class Types <code>Theme</code> Class Types <code>Subset</code> Type Types <code>ServerRenderer</code> Instance Types <code>ServerRenderedStory</code> Type Types <code>Story</code> Class Other exports <code>QuizRenderer</code> Instance Other exports <code>QuizApiService</code> Instance Other exports"},{"location":"reference/#conventions","title":"Conventions","text":"<p>These pages follow these conventions:</p> <ul> <li>Signatures come from the published declaration files. A <code>?</code> marks an optional parameter or field</li> <li>Since gives the release that added or last changed a member, when the release notes record it</li> <li>Examples use the namespace import <code>Storyteller</code>. With the CDN script, the same code runs against the <code>Storyteller</code> global</li> <li>Examples use placeholder values such as <code>demo-api-key</code> and <code>category-id</code>. Replace them with values from your Storyteller tenant</li> </ul>"},{"location":"reference/callbacks/","title":"Callbacks","text":"<p>The SDK reports events and asks for ad settings through delegate objects. You set one global delegate on <code>Storyteller.sharedInstance</code>, and you can set a delegate on each view. Every callback is optional. For setup steps, see Handle delegates and callbacks.</p>"},{"location":"reference/callbacks/#delegate-interfaces","title":"Delegate interfaces","text":"<p>The SDK defines three delegate interfaces:</p> Interface Set it on Callbacks <code>IStorytellerDelegate</code> <code>Storyteller.sharedInstance.delegate</code> <code>onUserActivityOccurred</code>, <code>onShareButtonTapped</code>, <code>getAdConfig</code>, <code>userNavigatedToApp</code> <code>IListViewDelegate</code> The <code>delegate</code> of a Stories or Clips row or grid <code>onDataLoadStarted</code>, <code>onDataLoadComplete</code>, <code>onPlayerDismissed</code> <code>IStorytellerClipsPlayerDelegate</code> The <code>delegate</code> of a <code>StorytellerClipsPlayerView</code> or <code>StorytellerEmbeddedClipsPlayerView</code> The <code>IListViewDelegate</code> callbacks, plus <code>onTopLevelBackTapped</code> <p>Assigning a delegate object replaces the previous one, so include every callback that you need in each assignment.</p>"},{"location":"reference/callbacks/#istorytellerdelegate","title":"<code>IStorytellerDelegate</code>","text":"<pre><code>interface IStorytellerDelegate {\n  onUserActivityOccurred?: (\n    type: ActivityType,\n    data: UserActivityData\n  ) =&gt; void;\n  onShareButtonTapped?: (\n    text: string,\n    title: string,\n    url: string\n  ) =&gt; Promise&lt;void&gt;;\n  getAdConfig?: (\n    adRequestInfo: StorytellerAdRequestInfo\n  ) =&gt; AdConfig | null;\n  userNavigatedToApp?: (url: string) =&gt; void;\n}\n</code></pre> <p>The global delegate handles events from every Story and Clip player on the page.</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    console.log(type, data.context);\n  },\n};\n</code></pre> <ul> <li>Guide: Handle global callbacks</li> </ul>"},{"location":"reference/callbacks/#onuseractivityoccurred","title":"<code>onUserActivityOccurred</code>","text":"<pre><code>onUserActivityOccurred?: (type: ActivityType, data: UserActivityData) =&gt; void\n</code></pre> <p>Called for each analytics event. The SDK ignores the return value.</p> Parameter Type Description <code>type</code> <code>ActivityType</code> The event name, such as <code>openedStory</code> <code>data</code> <code>UserActivityData</code> The event properties. Each event page lists the properties that it sets <p>The privacy options control the callback:</p> <ul> <li>The callback runs only when <code>enableUserActivityTracking</code> is <code>true</code></li> <li>Ad events reach the callback only when <code>enableAdTracking</code> is <code>true</code></li> <li>When <code>enableFullVideoAnalytics</code> is <code>false</code>, the SDK sets <code>storyId</code>, <code>storyTitle</code>, <code>storyDisplayTitle</code>, <code>pageId</code>, <code>pageTitle</code>, <code>clipId</code>, and <code>clipTitle</code> to <code>null</code></li> </ul> <p><code>data.context</code> holds the view's <code>configuration.context</code>, unless that value is <code>undefined</code>. Assign the delegate before <code>initialize</code> to receive the <code>sdkInitialized</code> event.</p> <ul> <li>Since: 10.0.0 moved the callback to the global delegate</li> <li>Guides: Integrate analytics, Story events, Clip events, Ad events</li> </ul>"},{"location":"reference/callbacks/#onsharebuttontapped","title":"<code>onShareButtonTapped</code>","text":"<pre><code>onShareButtonTapped?: (\n  text: string,\n  title: string,\n  url: string\n) =&gt; Promise&lt;void&gt;\n</code></pre> <p>Called when a user taps the link share button in the Story player or the Clips player. Implement it to replace the browser share sheet.</p> Parameter Type Description <code>text</code> <code>string</code> Share text. For a Clip, the Clip description <code>title</code> <code>string</code> Share title. For a Story, the Story title. For a Clip, the Clip description <code>url</code> <code>string</code> The link to share <p>The returned promise controls what happens next:</p> <ul> <li>Resolves: the SDK records the <code>shareSuccess</code> event and resumes playback</li> <li>Rejects: the SDK resumes playback without a <code>shareSuccess</code> event</li> <li>Missing or throws: the SDK calls <code>navigator.share</code> instead</li> </ul> <p>The player pauses while the share runs.</p> <ul> <li>Since: 10.0.0. Since 10.4.6, the SDK falls back to <code>navigator.share</code></li> <li>Guide: Handle global callbacks</li> </ul>"},{"location":"reference/callbacks/#getadconfig","title":"<code>getAdConfig</code>","text":"<pre><code>getAdConfig?: (adRequestInfo: StorytellerAdRequestInfo) =&gt; AdConfig | null\n</code></pre> <p>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.</p> Parameter Type Description <code>adRequestInfo</code> <code>StorytellerAdRequestInfo</code> The Story or Clip context of the ad slot <p>Return an ad configuration, or <code>null</code> to send no ad request. The SDK uses this shape of the declared <code>AdConfig</code> union:</p> <pre><code>interface 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</code></pre> Field Type Required Description <code>slot</code> <code>string</code> Yes Google Ad Manager ad unit, in the form <code>/[NETWORK_CODE]/[UNIT_CODE]</code>. A configuration without <code>slot</code> is not valid <code>customTargeting</code> <code>AdTargeting</code> No Key-value pairs for the ad request. Values are strings or arrays of strings <code>publisherProvidedId</code> <code>string</code> or <code>null</code> No Publisher Provided ID (PPID). The SDK trims whitespace and omits an empty value <code>type</code> <code>'doubleclick'</code> No Ad server type <p>The SDK adds its default targeting keys and lets your <code>customTargeting</code> values override them. When <code>enableAdTracking</code> is <code>false</code>, the SDK omits its default keys and <code>publisherProvidedId</code>, and still sends your <code>customTargeting</code>.</p> <p><code>AdConfig</code> and <code>AdTargeting</code> are not exported by name. The declared <code>AdConfig</code> union also includes <code>{ type: 'custom'; remoteUrl: string }</code>, which the SDK uses for Storyteller first-party ads. The SDK ignores that shape when your delegate returns it.</p> <ul> <li>Since: 10.0.0 moved the callback to the global delegate. <code>publisherProvidedId</code> was added in 10.13.6</li> <li>Guides: Google Ad Manager integration, Default Targeting, AdRequestInfo</li> </ul>"},{"location":"reference/callbacks/#usernavigatedtoapp","title":"<code>userNavigatedToApp</code>","text":"<pre><code>userNavigatedToApp?: (url: string) =&gt; void\n</code></pre> <p>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.</p> Parameter Type Description <code>url</code> <code>string</code> The action URL set in the Storyteller CMS <ul> <li>Since: 10.6.0</li> <li>Guide: Handle global callbacks</li> </ul>"},{"location":"reference/callbacks/#ilistviewdelegate","title":"<code>IListViewDelegate</code>","text":"<pre><code>interface IListViewDelegate {\n  onDataLoadStarted?: () =&gt; void;\n  onDataLoadComplete?: (\n    success: boolean,\n    error: Error | null,\n    dataCount: number\n  ) =&gt; void;\n  onPlayerDismissed?: () =&gt; void;\n}\n</code></pre> <p>A view delegate handles events from one view. The SDK fills callbacks that you leave out with no-op functions.</p> <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');\n\nstoryRow.delegate = {\n  onDataLoadStarted: () =&gt; console.log('Loading Stories'),\n  onDataLoadComplete: (success, error, dataCount) =&gt; {\n    console.log(success, error, dataCount);\n  },\n};\n</code></pre> <ul> <li>Since: 10.0.0 renamed these callbacks</li> <li>Guide: Handle view callbacks</li> </ul>"},{"location":"reference/callbacks/#ondataloadstarted","title":"<code>onDataLoadStarted</code>","text":"<pre><code>onDataLoadStarted?: () =&gt; void\n</code></pre> <p>Called each time the view starts loading its content. This happens after the constructor, after a source change (<code>categories</code>, <code>collection</code>, <code>clipId</code>, or <code>externalId</code>), on <code>reloadData</code>, and when a Clips view refreshes after its player closes.</p>"},{"location":"reference/callbacks/#ondataloadcomplete","title":"<code>onDataLoadComplete</code>","text":"<pre><code>onDataLoadComplete?: (\n  success: boolean,\n  error: Error | null,\n  dataCount: number\n) =&gt; void\n</code></pre> <p>Called when the content request finishes.</p> Parameter Type Description <code>success</code> <code>boolean</code> <code>true</code> when the request succeeded <code>error</code> <code>Error</code> or <code>null</code> <code>null</code> on success. On failure, the request error. When the failure is not an <code>Error</code>, the SDK passes an <code>Error</code> with the message <code>Network Error</code> <code>dataCount</code> <code>number</code> Stories views: the number of Stories loaded. Clips views: the number of Clips in the first page. Single-Clip players: <code>1</code>. <code>0</code> on failure <p>Later Clips pages load as users reach the end of the content, and they do not call this callback. See Clips paging.</p>"},{"location":"reference/callbacks/#onplayerdismissed","title":"<code>onPlayerDismissed</code>","text":"<pre><code>onPlayerDismissed?: () =&gt; void\n</code></pre> <p>Called when the Story or Clip player that the view opened is dismissed. A tap on the Clips player top-level back button calls <code>onTopLevelBackTapped</code> instead.</p>"},{"location":"reference/callbacks/#istorytellerclipsplayerdelegate","title":"<code>IStorytellerClipsPlayerDelegate</code>","text":"<pre><code>interface IStorytellerClipsPlayerDelegate extends IListViewDelegate {\n  onTopLevelBackTapped?: () =&gt; void;\n}\n</code></pre> <p>The delegate of <code>StorytellerClipsPlayerView</code> and <code>StorytellerEmbeddedClipsPlayerView</code>. It supports the <code>IListViewDelegate</code> callbacks.</p>"},{"location":"reference/callbacks/#ontoplevelbacktapped","title":"<code>onTopLevelBackTapped</code>","text":"<pre><code>onTopLevelBackTapped?: () =&gt; void\n</code></pre> <p>Called when a user taps the top-level back button. The button shows only when <code>topLevelBackButtonEnabled</code> is <code>true</code>. Without this callback, the SDK calls <code>window.history.back()</code>.</p> <pre><code>clipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <ul> <li>Since: 10.13.6</li> <li>Guide: Handle view callbacks</li> </ul>"},{"location":"reference/storyteller/","title":"Storyteller instance","text":"<p><code>Storyteller.sharedInstance</code> is the SDK singleton. You use it to initialize the SDK, set the global delegate, theme, and privacy options, and open Stories or Clips from your own code. <code>Storyteller.User</code> is a second singleton that stores user attributes. The SDK creates both when the script or package loads.</p>"},{"location":"reference/storyteller/#members-at-a-glance","title":"Members at a glance","text":"<p><code>Storyteller.sharedInstance</code> has these properties:</p> Property Type Access <code>version</code> <code>string</code> Read <code>isInitialized</code> <code>boolean</code> Read-only <code>isPlayerVisible</code> <code>boolean</code> Read-only <code>delegate</code> <code>IStorytellerDelegate</code> Read and write <code>theme</code> <code>Subset&lt;IUiTheme&gt;</code> Read and write <code>currentTheme</code> <code>IStorytellerTheme</code> Read-only <code>uiStyle</code> <code>UiStyle</code> Read-only <code>eventTrackingOptions</code> <code>StorytellerEventTrackingOptions</code> Read and write <code>customInstanceHost</code> <code>string</code> Write-only <code>currentApiKey</code> <code>string</code> or <code>null</code> Read-only <p>It has these methods:</p> Method Returns <code>initialize(apiKey, userInput?)</code> <code>Promise&lt;void&gt;</code> <code>getStoriesCount(categoryIds)</code> <code>Promise&lt;number&gt;</code> <code>getClipsCount(collectionId)</code> <code>Promise&lt;number&gt;</code> <code>openStory(id)</code> <code>Promise&lt;void&gt;</code> <code>openStoryByExternalId(externalId)</code> <code>Promise&lt;void&gt;</code> <code>openPage(pageId)</code> <code>Promise&lt;void&gt;</code> <code>openCategory(categoryId, storyId?)</code> <code>Promise&lt;void&gt;</code> <code>openCollection(collectionId, destination?, openedReason?)</code> <code>Promise&lt;void&gt;</code> <code>openClipByExternalId(collectionId, externalId)</code> <code>Promise&lt;void&gt;</code> <code>dismissPlayer(animated)</code> <code>void</code> <code>disablePlayback()</code> <code>void</code> <code>enablePlayback()</code> <code>void</code> <code>enableLogging()</code> <code>void</code> <p>Deprecated members and an internal member are listed at the end of Methods.</p>"},{"location":"reference/storyteller/#properties","title":"Properties","text":"<p>These properties are on <code>Storyteller.sharedInstance</code>.</p>"},{"location":"reference/storyteller/#version","title":"<code>version</code>","text":"<pre><code>version: string\n</code></pre> <p>The SDK version, such as <code>'11.0.0'</code>. See Use additional SDK methods.</p>"},{"location":"reference/storyteller/#isinitialized","title":"<code>isInitialized</code>","text":"<pre><code>get isInitialized(): boolean\n</code></pre> <p><code>true</code> after an <code>initialize</code> call succeeds. Once <code>true</code>, it stays <code>true</code> for the rest of the page session, including while a later <code>initialize</code> call runs.</p> <ul> <li>Since: 10.0.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#isplayervisible","title":"<code>isPlayerVisible</code>","text":"<pre><code>get isPlayerVisible(): boolean\n</code></pre> <p><code>true</code> while a Story or Clip player is open, and <code>false</code> after it is dismissed.</p> <ul> <li>Since: 10.0.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#delegate","title":"<code>delegate</code>","text":"<pre><code>get delegate(): IStorytellerDelegate\nset delegate(delegateObj: IStorytellerDelegate)\n</code></pre> <p>The global callbacks for Stories, Clips, analytics, sharing, ads, and in-app links. Assigning an object replaces all four callbacks, so a callback that you leave out is cleared. Reading the property returns a new object that holds the current callbacks.</p> <pre><code>Storyteller.sharedInstance.delegate = {\n  onUserActivityOccurred: (type, data) =&gt; {\n    console.log(type, data.context);\n  },\n};\n</code></pre> <ul> <li>Type: <code>IStorytellerDelegate</code></li> <li>Since: 10.0.0 moved the delegate to the shared instance</li> <li>Guide: Handle global callbacks</li> </ul>"},{"location":"reference/storyteller/#theme","title":"<code>theme</code>","text":"<pre><code>get theme(): Subset&lt;IUiTheme&gt;\nset theme(theme: Subset&lt;IUiTheme&gt;)\n</code></pre> <p>The global theme for every view. Pass a <code>UiTheme</code> or a plain object with optional <code>light</code> and <code>dark</code> themes. A view's <code>configuration.theme</code> overrides the global theme for that view.</p> <p>Note</p> <p>Each <code>initialize</code> call replaces the global theme with a default <code>UiTheme</code>. Set <code>theme</code> after <code>initialize</code> resolves, and set it again after a later <code>initialize</code> call, such as a user change.</p> <pre><code>await Storyteller.sharedInstance.initialize('demo-api-key');\n\nStoryteller.sharedInstance.theme = new Storyteller.UiTheme({\n  light: { colors: { primary: '#1C62EB' } },\n});\n</code></pre> <ul> <li>Guide: Customize themes</li> </ul>"},{"location":"reference/storyteller/#currenttheme","title":"<code>currentTheme</code>","text":"<pre><code>get currentTheme(): IStorytellerTheme\n</code></pre> <p>The resolved global <code>Theme</code> for the current color scheme. The SDK picks the <code>light</code> or <code>dark</code> theme from <code>theme</code>, fills unset values with SDK defaults, and rebuilds it when the system color scheme changes. The value exists after <code>initialize</code> runs or after you assign <code>theme</code>.</p>"},{"location":"reference/storyteller/#uistyle","title":"<code>uiStyle</code>","text":"<pre><code>get uiStyle(): UiStyle\n</code></pre> <p>The <code>UiStyle</code> of the global theme. The SDK also uses it for the players it creates for the open methods and hash URLs when no matching view exists on the page. On your pages the value is <code>UiStyle.auto</code>. Set a view's style with <code>configuration.uiStyle</code>.</p>"},{"location":"reference/storyteller/#eventtrackingoptions","title":"<code>eventTrackingOptions</code>","text":"<pre><code>get eventTrackingOptions(): StorytellerEventTrackingOptions\nset eventTrackingOptions(newOptions: Partial&lt;StorytellerEventTrackingOptions&gt;)\n</code></pre> <p>The privacy and tracking options. Every option defaults to <code>true</code>, and <code>disabledFunctionalFeatures</code> defaults to <code>[]</code>.</p> <p>Assigning an object replaces every option: a field that you leave out returns to its default. To change one option, spread the current value:</p> <pre><code>Storyteller.sharedInstance.eventTrackingOptions = {\n  ...Storyteller.sharedInstance.eventTrackingOptions,\n  enableAdTracking: false,\n};\n</code></pre> <p>Reading the property returns the effective values. When <code>enableFunctionalCookies</code> is <code>false</code>, <code>enablePersonalization</code> and <code>enableStorytellerTracking</code> read as <code>false</code>. Set the options before <code>initialize</code> when <code>enableRemoteViewingStore</code> must apply to the stored user ID.</p> <ul> <li>Type: <code>StorytellerEventTrackingOptions</code></li> <li>Since: 10.7.0. <code>enableAdTracking</code> was added in 10.9.0 and <code>enableFullVideoAnalytics</code> in 10.11.0</li> <li>Guide: Control privacy and tracking</li> </ul>"},{"location":"reference/storyteller/#custominstancehost","title":"<code>customInstanceHost</code>","text":"<pre><code>set customInstanceHost(customInstanceHost: string)\n</code></pre> <p>Sets the API host for SDK requests in place of the default Storyteller API host. The SDK removes a trailing <code>/</code> and stores the value in local storage under <code>Storyteller.customInstanceHost</code>. The property has no getter, and no task guide covers it.</p> <ul> <li>Since: 8.0.0</li> </ul>"},{"location":"reference/storyteller/#currentapikey","title":"<code>currentApiKey</code>","text":"<pre><code>get currentApiKey(): string | null\n</code></pre> <p>The API key from the latest <code>initialize</code> call. Before that call, it returns the key stored in local storage from an earlier page load, or <code>null</code> when no key is stored.</p>"},{"location":"reference/storyteller/#methods","title":"Methods","text":"<p>These methods are on <code>Storyteller.sharedInstance</code>.</p>"},{"location":"reference/storyteller/#initialize","title":"<code>initialize</code>","text":"<pre><code>initialize(apiKey: string, userInput?: UserInput): Promise&lt;void&gt;\n</code></pre> <p>Starts the SDK for an API key and user. Create views after the promise resolves.</p> Parameter Type Required Default Description <code>apiKey</code> <code>string</code> Yes None Your Storyteller Web SDK API key <code>userInput</code> <code>UserInput</code> No <code>{}</code> User options. Pass a plain object such as <code>{ externalId: 'user-id' }</code> <p><code>UserInput</code> has one optional field, <code>externalId</code>:</p> <pre><code>class UserInput {\n  constructor(public externalId?: string | null) {}\n}\n</code></pre> <code>externalId</code> value Result A string Sets the current user. The SDK stores a SHA-256 hash of the ID. A new ID resets the user data stored in the browser, including user attributes <code>null</code> Clears the user ID and resets the stored user data Omitted Keeps the stored user ID. The SDK creates a random ID when none is stored, or when <code>apiKey</code> differs from the previous key <p>When <code>eventTrackingOptions.enableRemoteViewingStore</code> is <code>false</code>, the SDK deletes the stored user ID and ignores <code>externalId</code>.</p> <p>The call behaves as follows:</p> <ul> <li>Concurrent calls with the same <code>apiKey</code> and <code>externalId</code> return the same promise. A call with different values waits for the active call to settle, then runs</li> <li>After a successful call, later calls apply the new user and resolve without a new Settings request. With logging enabled, the SDK logs <code>Storyteller has already been initialized. Reusing the existing instance.</code></li> <li>The SDK records the <code>sdkInitialized</code> activity event after the Settings request succeeds or fails</li> </ul> <p>The promise rejects with these values:</p> Condition Rejection value <code>apiKey</code> is empty and the SDK is not initialized The string <code>Storyteller couldn't be initialized because no API key was provided.</code> The Settings request returns HTTP 401 or 404 An <code>Error</code> whose message starts with <code>InvalidApiKeyError</code> The Settings request returns HTTP 408 An <code>Error</code> whose message starts with <code>NetworkTimeoutError</code> Any other Settings failure, including an empty response An <code>Error</code> whose message starts with <code>NetworkError</code> User setup fails The error from that step <p>The error classes are not exported. Check the message prefix to tell them apart.</p> <pre><code>try {\n  await Storyteller.sharedInstance.initialize('demo-api-key', {\n    externalId: 'user-id',\n  });\n} catch (error) {\n  console.error('Storyteller could not start.', error);\n}\n</code></pre> <ul> <li>Since: 11.0.0 shares one startup between concurrent matching calls</li> <li>Guides: Show your first Story row, Handle initialization errors, Identify and personalize users</li> </ul>"},{"location":"reference/storyteller/#getstoriescount","title":"<code>getStoriesCount</code>","text":"<pre><code>getStoriesCount(categoryIds: string[]): Promise&lt;number&gt;\n</code></pre> <p>Returns the number of available Stories in the given categories. The SDK sends one count request per category and adds the results.</p> Parameter Type Required Default Description <code>categoryIds</code> <code>string[]</code> Yes None Story category IDs <ul> <li>Returns: the total count. An empty array resolves to <code>0</code> at once, without a request</li> <li>Waits: until an <code>initialize</code> call succeeds. The promise stays pending until then</li> <li>Rejects: when a count request fails, or a response is empty or has no numeric count</li> <li>Since: 10.13.16</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#getclipscount","title":"<code>getClipsCount</code>","text":"<pre><code>getClipsCount(collectionId: string): Promise&lt;number&gt;\n</code></pre> <p>Returns the number of available Clips in a collection.</p> Parameter Type Required Default Description <code>collectionId</code> <code>string</code> Yes None Clips collection ID <ul> <li>Waits: until an <code>initialize</code> call succeeds. The promise stays pending until then</li> <li>Rejects: with <code>Error('Collection is required to load Clips count')</code> for an empty ID, and when the request fails or the response is empty or has no numeric count</li> <li>Since: 10.13.16</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#open-methods","title":"Open methods","text":"<p>The open methods show a Story or Clip player from your code. They share this behavior:</p> <ol> <li>The SDK looks for the content in the views on the page. It uses only views with URLs enabled, which means the <code>player.disableUrls</code> or <code>clipPlayer.disableUrls</code> theme property is <code>false</code>.</li> <li>When a view has the content, the SDK sets <code>location.hash</code> to that view's player URL, such as <code>#top-stories/story-id</code>.</li> <li>Otherwise, the SDK loads the content from the API and opens it in a default player at <code>#stories/...</code> or <code>#clips/...</code>.</li> <li>The promise resolves after the SDK sets <code>location.hash</code>. It rejects when the SDK cannot load the content or the content does not exist.</li> </ol> <p>The rejection value can be an <code>Error</code> or a string. Handle every rejection:</p> <pre><code>try {\n  await Storyteller.sharedInstance.openStory('story-id');\n} catch (error) {\n  console.error('The Story could not be opened.', error);\n}\n</code></pre> <p>Call the open methods after <code>initialize</code> resolves. See Basename for the hash URL format.</p>"},{"location":"reference/storyteller/#openstory","title":"<code>openStory</code>","text":"<pre><code>openStory(id: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story with this Story ID. The Story plays in single-Story mode.</p> Parameter Type Required Default Description <code>id</code> <code>string</code> Yes None Story ID <ul> <li>Rejects: when the Story cannot be loaded, or with the string <code>No Story with the provided ID was found.</code></li> <li>Since: 10.7.0 made the method async</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#openstorybyexternalid","title":"<code>openStoryByExternalId</code>","text":"<pre><code>openStoryByExternalId(externalId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story with this external ID. The Story plays in single-Story mode.</p> Parameter Type Required Default Description <code>externalId</code> <code>string</code> Yes None Story external ID <ul> <li>Rejects: when the Story cannot be loaded, or with the string <code>No Story with the provided External ID was found.</code></li> <li>Since: 10.7.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#openpage","title":"<code>openPage</code>","text":"<pre><code>openPage(pageId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story that contains this Page, starting at the Page.</p> Parameter Type Required Default Description <code>pageId</code> <code>string</code> Yes None Story Page ID <ul> <li>Rejects: when the SDK cannot load a Story for the Page</li> <li>Since: 10.7.0 made the method async</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#opencategory","title":"<code>openCategory</code>","text":"<pre><code>openCategory(categoryId: string, storyId?: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Story player for a category. On the page, the SDK uses a Stories view whose only category is <code>categoryId</code>.</p> Parameter Type Required Default Description <code>categoryId</code> <code>string</code> Yes None Story category ID <code>storyId</code> <code>string</code> No None Story to open first. When it is missing or not in the category, the first Story in the category opens <ul> <li>Rejects: when the category cannot be loaded</li> <li>Since: 10.7.0 made the method async</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#opencollection","title":"<code>openCollection</code>","text":"<pre><code>openCollection(\n  collectionId: string,\n  destination?: { categoryId?: string; clipId?: string },\n  openedReason?: OpenedReason.deepLink\n): Promise&lt;void&gt;\n</code></pre> <p>Opens the Clips player for a collection.</p> Parameter Type Required Default Description <code>collectionId</code> <code>string</code> Yes None Clips collection ID <code>destination</code> <code>{ categoryId?: string; clipId?: string }</code> No None Clip or Clip category to show first. <code>clipId</code> takes priority when you pass both. When the destination is missing or not found, the first Clip in the collection opens <code>openedReason</code> <code>OpenedReason.deepLink</code> No Set by the SDK The <code>OpenedReason</code> reported in analytics events. <code>OpenedReason.deepLink</code> is the only accepted value <ul> <li>Rejects: when the collection cannot be loaded</li> <li>Since: 10.7.0 made the method async and added <code>destination</code></li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#openclipbyexternalid","title":"<code>openClipByExternalId</code>","text":"<pre><code>openClipByExternalId(collectionId: string, externalId: string): Promise&lt;void&gt;\n</code></pre> <p>Opens the Clips player for a collection at the Clip with this external ID. When no view on the page has the Clip, the SDK loads collection pages until it finds the Clip, up to 100 pages.</p> Parameter Type Required Default Description <code>collectionId</code> <code>string</code> Yes None Clips collection ID <code>externalId</code> <code>string</code> Yes None Clip external ID <ul> <li>Rejects: when the collection cannot be loaded, or with a string message when the collection does not contain the Clip</li> <li>Since: 10.7.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#dismissplayer","title":"<code>dismissPlayer</code>","text":"<pre><code>dismissPlayer(animated: boolean): void\n</code></pre> <p>Closes the open Story or Clip player. It has no effect when no player is open. The dismissed event reports <code>DismissedReason.instanceMethod</code>. A <code>StorytellerEmbeddedClipsPlayerView</code> ignores this call.</p> Parameter Type Required Default Description <code>animated</code> <code>boolean</code> Yes None <code>true</code> plays the close animation <ul> <li>Since: 10.0.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#disableplayback","title":"<code>disablePlayback</code>","text":"<pre><code>disablePlayback(): void\n</code></pre> <p>Pauses the open Story player and the active Clip video. Players that open while playback is disabled stay paused.</p> <ul> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#enableplayback","title":"<code>enablePlayback</code>","text":"<pre><code>enablePlayback(): void\n</code></pre> <p>Allows playback again after <code>disablePlayback</code>, and resumes the open Story player and the active Clip. Playback is enabled by default.</p> <ul> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#enablelogging","title":"<code>enableLogging</code>","text":"<pre><code>enableLogging(): void\n</code></pre> <p>Turns on SDK info, warning, and log messages in the browser console. The SDK always writes errors to the console, with or without this call.</p> <ul> <li>Since: 10.0.0</li> <li>Guide: Use additional SDK methods</li> </ul>"},{"location":"reference/storyteller/#deprecated-members","title":"Deprecated members","text":"<p>These members still work in 11.0.0. Replace them with the members listed:</p> Member Behavior Replacement <code>openClip(id: string, onError?: (message: string) =&gt; void): void</code> Opens a Clip that a Clips view on the page has loaded. Calls <code>onError</code> with a message when no view has the Clip <code>openCollection</code> or <code>openClipByExternalId</code> <code>enableEventTracking(): void</code> Sets every tracking option to its default <code>eventTrackingOptions</code> <code>disableEventTracking(): void</code> Sets every tracking option to its default, except <code>enableStorytellerTracking: false</code> <code>eventTrackingOptions</code> <code>get currentUserId(): string</code> Always returns <code>''</code>. Deprecated in 10.11.0 None"},{"location":"reference/storyteller/#internal-members","title":"Internal members","text":"<p>The declarations include <code>requestUserActivityHistory_(): Promise&lt;void&gt;</code>. It reloads the current user's activity history, a step that <code>initialize</code> already runs. No guide documents it, and integrations do not need to call it.</p>"},{"location":"reference/storyteller/#storytelleruser","title":"<code>Storyteller.User</code>","text":"<p><code>Storyteller.User</code> stores user attributes for personalization and audience targeting. The SDK keeps them in local storage and adds them to its content requests.</p> <pre><code>Storyteller.User.setUserAttribute('location', 'New York');\n</code></pre> <p>Set attributes after <code>initialize</code> resolves. A new <code>externalId</code> in <code>initialize</code> clears the stored attributes. See Identify and personalize users.</p> Member Returns <code>setUserAttribute(key, value)</code> <code>true</code>, <code>-1</code>, or <code>undefined</code> <code>getUserAttribute(key)</code> <code>string</code> or <code>undefined</code> <code>getUserAttributes()</code> <code>Record&lt;string, string&gt;</code> <code>removeUserAttribute(key)</code> <code>void</code> <code>setLocale(locale)</code> <code>void</code> <code>locale</code> <code>string</code> or <code>undefined</code>"},{"location":"reference/storyteller/#setuserattribute","title":"<code>setUserAttribute</code>","text":"<pre><code>setUserAttribute(key: string, value: string): true | -1 | undefined\n</code></pre> <p>Stores one attribute. An existing value for the key is replaced.</p> Parameter Type Required Default Description <code>key</code> <code>string</code> Yes None Attribute name <code>value</code> <code>string</code> Yes None Attribute value <ul> <li>Returns: <code>true</code> when the attribute is stored. <code>undefined</code> when <code>eventTrackingOptions.enablePersonalization</code> is <code>false</code>: the SDK does not store the attribute and logs a warning, which shows when logging is enabled. <code>-1</code> when the stored value cannot be read back</li> <li>Throws: <code>Error('Key and value are required when setting user attributes')</code> when <code>key</code> or <code>value</code> is empty</li> <li>Guide: Setting User Attributes</li> </ul>"},{"location":"reference/storyteller/#getuserattribute","title":"<code>getUserAttribute</code>","text":"<pre><code>getUserAttribute(key: string): string | undefined\n</code></pre> <p>Returns the stored value for <code>key</code>, or <code>undefined</code> when none is stored.</p>"},{"location":"reference/storyteller/#getuserattributes","title":"<code>getUserAttributes</code>","text":"<pre><code>getUserAttributes(): IUserAttributes\n</code></pre> <p>Returns all stored attributes as an object. <code>IUserAttributes</code> is <code>Record&lt;string, string&gt;</code>. Returns <code>{}</code> when none are stored.</p>"},{"location":"reference/storyteller/#removeuserattribute","title":"<code>removeUserAttribute</code>","text":"<pre><code>removeUserAttribute(key: string): void\n</code></pre> <p>Removes one attribute.</p> <ul> <li>Guide: Removing User Attributes</li> </ul>"},{"location":"reference/storyteller/#setlocale","title":"<code>setLocale</code>","text":"<pre><code>setLocale(locale: string): void\n</code></pre> <p>Sets the Clips locale. The SDK stores it as the <code>stLocale</code> user attribute, so it follows the same rules as <code>setUserAttribute</code>.</p> Parameter Type Required Default Description <code>locale</code> <code>string</code> Yes None Language code, such as <code>'es'</code> <ul> <li>Throws: the <code>setUserAttribute</code> error when <code>locale</code> is empty</li> <li>Since: 10.2.0</li> <li>Guide: Updating the Clips locale</li> </ul>"},{"location":"reference/storyteller/#locale","title":"<code>locale</code>","text":"<pre><code>get locale(): string | undefined\n</code></pre> <p>The stored <code>stLocale</code> attribute, or <code>undefined</code>.</p> <p>The declarations also include <code>parseUserAttributesToQueryStringAlphabetically(): string</code>. The SDK uses it to build request query strings from the stored attributes.</p>"},{"location":"reference/types/","title":"Types and enums","text":"<p>This page lists the enums, data types, theme classes, and server rendering helpers that the SDK exports. Theme properties are covered in Customize themes, and event properties in the analytics event pages.</p>"},{"location":"reference/types/#enums","title":"Enums","text":"<p>Every enum value is a string equal to its member name. In TypeScript, pass the enum member, such as <code>Storyteller.UiStyle.dark</code>. In JavaScript, you can also pass the string, such as <code>'dark'</code>.</p>"},{"location":"reference/types/#uistyle","title":"<code>UiStyle</code>","text":"<pre><code>enum UiStyle {\n  auto = 'auto',\n  light = 'light',\n  dark = 'dark',\n}\n</code></pre> <p>Selects the <code>light</code> or <code>dark</code> theme of a <code>UiTheme</code>. <code>auto</code> follows the system color scheme. Set it with <code>configuration.uiStyle</code> or the <code>data-ui-style</code> container attribute. See uiStyle.</p>"},{"location":"reference/types/#celltype","title":"<code>CellType</code>","text":"<pre><code>enum StorytellerListViewCellType {\n  round = 'round',\n  square = 'square',\n}\n</code></pre> <p>Exported as <code>CellType</code>. Sets the tile shape of a row. The default is <code>square</code>. See cellType.</p>"},{"location":"reference/types/#activitytype","title":"<code>ActivityType</code>","text":"<p>The <code>type</code> argument of <code>onUserActivityOccurred</code>. The event pages list when each event fires and its properties:</p> Area Values Reference SDK <code>sdkInitialized</code> SDK initialization Stories and Clips <code>actionButtonTapped</code>, <code>shareButtonTapped</code>, <code>shareSuccess</code> Story events, Clip events Stories <code>openedStory</code>, <code>dismissedStory</code>, <code>skippedStory</code>, <code>completedStory</code>, <code>openedPage</code>, <code>previousPage</code>, <code>previousStory</code> Story events Story captions <code>enabledStoryCaptions</code>, <code>disabledStoryCaptions</code> Story caption events Polls <code>votedPoll</code> Poll events Quizzes <code>triviaQuizQuestionAnswered</code>, <code>triviaQuizCompleted</code> Quiz events Ads <code>openedAd</code>, <code>dismissedAd</code>, <code>pausedAdPage</code>, <code>resumedAdPage</code>, <code>finishedAd</code>, <code>skippedAd</code>, <code>adActionButtonTapped</code>, <code>viewedAdPageFirstQuartile</code>, <code>viewedAdPageMidpoint</code>, <code>viewedAdPageThirdQuartile</code>, <code>viewedAdPageComplete</code> Ad events Clips <code>openedClip</code>, <code>dismissedClip</code>, <code>finishedClip</code>, <code>nextClip</code>, <code>previousClip</code>, <code>completedLoop</code>, <code>pausedClip</code>, <code>resumedClip</code>, <code>likedClip</code>, <code>unlikedClip</code>, <code>openedCategory</code>, <code>dismissedCategory</code> Clip events Clip captions <code>enabledClipCaptions</code>, <code>disabledClipCaptions</code> Clip caption events <p>The source groups these values as no longer used or deprecated:</p> <ul> <li><code>completedPage</code> and <code>skippedPage</code>. The Story player still records these two events, and the event pages do not document them</li> <li><code>swipedUp</code>, <code>viewedPage</code>, <code>completedAd</code>, <code>swipedUpOnAd</code>, <code>previousAd</code>, <code>impression</code>, <code>readyToPlay</code>, <code>mediaStarted</code>, <code>bufferingStarted</code>, <code>bufferingEnded</code>. The SDK does not record these events</li> </ul>"},{"location":"reference/types/#openedreason","title":"<code>OpenedReason</code>","text":"<p>The <code>openedReason</code> property of open events:</p> Area Values Stories <code>storyListTap</code>, <code>deepLink</code>, <code>swipe</code>, <code>automaticPlayback</code>, <code>tap</code> Clips <code>clipListTap</code>, <code>categoryListTap</code>, <code>categoryBackTap</code>, <code>deepLink</code> <p>See OpenedReason for each value. <code>openCollection</code> accepts <code>OpenedReason.deepLink</code> as its third argument.</p>"},{"location":"reference/types/#dismissedreason","title":"<code>DismissedReason</code>","text":"<p>The <code>dismissedReason</code> property of dismiss events:</p> Area Values Stories and Clips <code>backgroundTapped</code>, <code>instanceMethod</code>, <code>windowUnload</code> Stories <code>closeButtonTapped</code>, <code>swipedDown</code>, <code>swipedFirstStory</code>, <code>swipedFinalStory</code>, <code>skippedFinalPage</code>, <code>completedFinalPage</code>, <code>backTapped</code>, <code>escapeKeyPressed</code> Clips <code>backButtonTapped</code> <p>See DismissedReason for each value. <code>dismissPlayer</code> reports <code>instanceMethod</code>.</p>"},{"location":"reference/types/#storytellertrackedfunctionalfeature","title":"<code>StorytellerTrackedFunctionalFeature</code>","text":"<pre><code>enum StorytellerTrackedFunctionalFeature {\n  all = 'all',\n  clipLikes = 'clipLikes',\n  clipShares = 'clipShares',\n  clipViewedStatus = 'clipViewedStatus',\n  pageReadStatus = 'pageReadStatus',\n  pollVotes = 'pollVotes',\n  triviaQuizAnswers = 'triviaQuizAnswers',\n}\n</code></pre> <p>The items of <code>eventTrackingOptions.disabledFunctionalFeatures</code>. <code>all</code> disables every item. See Disabled functional features.</p> <p>Note</p> <p>The npm package exports this enum at runtime. The CDN script does not, so <code>Storyteller.StorytellerTrackedFunctionalFeature</code> is <code>undefined</code> there. Pass the string values instead, such as <code>['pageReadStatus']</code>.</p>"},{"location":"reference/types/#theme-enums","title":"Theme enums","text":"<p>Three enums set theme properties. See Customize themes for each property:</p> Enum Values Theme properties <code>Alignment</code> <code>start</code>, <code>center</code>, <code>end</code> <code>storyTiles.title.alignment</code>, <code>storyTiles.rectangularTile.chip.alignment</code> <code>ButtonAlignment</code> <code>left</code>, <code>center</code>, <code>right</code> <code>player.actionButton.alignment</code> <code>TextCase</code> <code>default</code>, <code>upper</code>, <code>lower</code> <code>buttons.textCase</code>"},{"location":"reference/types/#privacy-options","title":"Privacy options","text":"<p>The type of <code>Storyteller.sharedInstance.eventTrackingOptions</code>.</p>"},{"location":"reference/types/#storytellereventtrackingoptions","title":"<code>StorytellerEventTrackingOptions</code>","text":"<pre><code>type StorytellerEventTrackingOptions = {\n  disabledFunctionalFeatures: StorytellerTrackedFunctionalFeature[];\n  enableAdTracking: boolean;\n  enableFullVideoAnalytics: boolean;\n  enableFunctionalCookies: boolean;\n  enablePersonalization: boolean;\n  enableRemoteViewingStore: boolean;\n  enableStorytellerTracking: boolean;\n  enableUserActivityTracking: boolean;\n};\n</code></pre> Field Default Effect when changed from the default <code>disabledFunctionalFeatures</code> <code>[]</code> Stops tracking the listed features <code>enableAdTracking</code> <code>true</code> <code>false</code> stops ad events and removes Story and Clip details from ad requests <code>enableFullVideoAnalytics</code> <code>true</code> <code>false</code> sets Story, Page, and Clip IDs and titles to <code>null</code> in callback data <code>enableFunctionalCookies</code> <code>true</code> <code>false</code> stops non-essential local storage, and turns off personalization and Storyteller tracking <code>enablePersonalization</code> <code>true</code> <code>false</code> stops sending user IDs and user attributes for personalization <code>enableRemoteViewingStore</code> <code>true</code> <code>false</code> keeps user IDs off backend services and keeps viewing activity on the device <code>enableStorytellerTracking</code> <code>true</code> <code>false</code> stops storing analytics events on Storyteller servers <code>enableUserActivityTracking</code> <code>true</code> <code>false</code> stops <code>onUserActivityOccurred</code> calls"},{"location":"reference/types/#event-data","title":"Event data","text":"<p>The data types of analytics events.</p>"},{"location":"reference/types/#useractivitydata","title":"<code>UserActivityData</code>","text":"<p>The <code>data</code> argument of <code>onUserActivityOccurred</code>. Every field is optional, and each event sets a subset. The event pages list the fields of each event.</p> Area Fields and types Context <code>context</code> (<code>unknown</code>): the view's <code>configuration.context</code> Stories and Pages <code>storyId</code>, <code>storyTitle</code>, <code>storyDisplayTitle</code>, <code>pageId</code>, <code>pageTitle</code> (<code>string</code>, or <code>null</code> when <code>enableFullVideoAnalytics</code> is <code>false</code>); <code>storyIndex</code>, <code>storyPageCount</code>, <code>pageIndex</code>, <code>durationViewed</code>, <code>pagesViewed</code>, <code>contentLength</code> (<code>number</code>); <code>storyReadStatus</code> (<code>string</code>); <code>storyPlaybackMode</code> (<code>'list'</code> or <code>'singleStory'</code>); <code>pageType</code> (<code>'image'</code>, <code>'video'</code>, <code>'poll'</code>, or <code>'triviaQuiz'</code>); <code>pageHasAction</code> (<code>boolean</code>); <code>pageActionText</code>, <code>pageActionUrl</code> (<code>string</code> or <code>null</code>) Navigation <code>openedReason</code> (<code>OpenedReason</code>); <code>dismissedReason</code> (<code>DismissedReason</code>); <code>shareMethod</code> (<code>'share'</code>, <code>'shareMedia'</code>, <code>'shareLink'</code>, or <code>''</code>) Categories <code>categories</code> (<code>string[]</code>); <code>categoryDetails</code> (<code>CategoryDetail[]</code>); <code>currentCategory</code> (<code>CurrentCategory</code>); <code>categoryId</code>, <code>categoryName</code> (<code>string</code>) Ads <code>adId</code>, <code>adStrategy</code> (<code>string</code>); <code>advertiserName</code> (<code>string</code> or <code>null</code>); <code>adType</code> (<code>'stories'</code> or <code>'clips'</code>); <code>adPlacement</code> (<code>'betweenClips'</code>, <code>'betweenStories'</code>, <code>'betweenStoriesAndPages'</code>, or <code>'betweenPages'</code>) Polls <code>pollAnswerId</code> (<code>string</code>) Quizzes <code>triviaQuizId</code>, <code>triviaQuizQuestionId</code>, <code>triviaQuizAnswerId</code>, <code>triviaQuizTitle</code> (<code>string</code>); <code>triviaQuizScore</code> (<code>number</code>) Clips <code>clipId</code>, <code>clipTitle</code> (<code>string</code>, or <code>null</code> when <code>enableFullVideoAnalytics</code> is <code>false</code>); <code>collection</code> (<code>string</code>); <code>clipActionText</code>, <code>clipActionUrl</code> (<code>string</code> or <code>null</code>); <code>clipIndex</code>, <code>clipsViewed</code>, <code>loopsViewed</code> (<code>number</code>); <code>clipHasAction</code> (<code>boolean</code>) Captions <code>captionsEnabled</code> (<code>boolean</code>) SDK initialization <code>initializationSucceeded</code>, <code>enableAdTracking</code>, <code>enableFullVideoAnalytics</code>, <code>enablePersonalization</code>, <code>enableRemoteViewingStore</code>, <code>enableStorytellerTracking</code>, <code>enableUserActivityTracking</code> (<code>boolean</code>); <code>appId</code>, <code>screenResolution</code> (<code>string</code> or <code>null</code>); <code>deviceBrand</code>, <code>deviceModel</code>, <code>operatingSystem</code>, <code>osVersion</code> (<code>string</code>); <code>deviceType</code> (<code>'Phone'</code>, <code>'Tablet'</code>, <code>'TV'</code>, or <code>'Desktop'</code>) <p>The category types have these fields:</p> <pre><code>class CategoryDetail {\n  name: string;\n  id?: string;\n  type: string;\n  placement?: string;\n  externalId?: string;\n}\n\nclass CurrentCategory {\n  title: string;\n  id?: string;\n  placement?: string;\n}\n</code></pre> <p>The SDK exports <code>UserActivityData</code> as a class. The callback receives a plain object with these fields.</p>"},{"location":"reference/types/#activityeventdetail","title":"<code>ActivityEventDetail</code>","text":"<pre><code>class ActivityEventDetail {\n  type: ActivityType;\n  data: UserActivityData;\n  constructor(type: ActivityType, data: UserActivityData);\n}\n</code></pre> <p>A pair of event type and event data. The SDK exports the class, but no SDK callback receives it in 11.0.0.</p>"},{"location":"reference/types/#ad-request-data","title":"Ad request data","text":"<p>The <code>adRequestInfo</code> argument of <code>getAdConfig</code>. See AdRequestInfo.</p>"},{"location":"reference/types/#storytelleradrequestinfo","title":"<code>StorytellerAdRequestInfo</code>","text":"<pre><code>type StorytellerAdRequestInfo =\n  | StorytellerStoriesAdRequestInfo\n  | StorytellerClipsAdRequestInfo;\n</code></pre> <p>Check for the <code>story</code> field to tell the variants apart:</p> <pre><code>const isStoryAd = (\n  info: Storyteller.StorytellerAdRequestInfo\n): info is Storyteller.StorytellerStoriesAdRequestInfo =&gt; 'story' in info;\n</code></pre>"},{"location":"reference/types/#storytellerstoriesadrequestinfo","title":"<code>StorytellerStoriesAdRequestInfo</code>","text":"<pre><code>type StorytellerStoriesAdRequestInfo = {\n  placement: string;\n  categories: string[];\n  story: {\n    id: '';\n    categories: CategoryDetail[];\n  };\n};\n</code></pre> Field Description <code>placement</code> Placement code of the Story category that matches the first category ID of the view. <code>''</code> when none matches <code>categories</code> Category IDs of the view that shows the Story <code>story.categories</code> Categories of the Story, as <code>CategoryDetail</code> objects <code>story.id</code> Always <code>''</code>. Deprecated <p>See Stories AdRequestInfo.</p>"},{"location":"reference/types/#storytellerclipsadrequestinfo","title":"<code>StorytellerClipsAdRequestInfo</code>","text":"<pre><code>type StorytellerClipsAdRequestInfo = {\n  collection: string;\n  clip: {\n    id: '';\n    categories: ClipCategory[];\n  };\n  nextClip?: {\n    categories: ClipCategory[];\n  };\n};\n</code></pre> Field Description <code>collection</code> Collection ID <code>clip.categories</code> Categories of the current Clip <code>nextClip.categories</code> Categories of the next Clip. <code>nextClip</code> is absent when no next Clip exists <code>clip.id</code> Always <code>''</code>. Deprecated <p><code>ClipCategory</code> has these fields:</p> <pre><code>interface ClipCategory {\n  id: string;\n  name: string;\n  externalId: string;\n  placement: string | null;\n  type: string;\n  displayTitle: string;\n  availableForNavigation: boolean;\n}\n</code></pre> <p>See Clips AdRequestInfo.</p>"},{"location":"reference/types/#theme-classes","title":"Theme classes","text":"<p>The classes and types that build a theme. Customize themes lists every theme property and default.</p>"},{"location":"reference/types/#uitheme","title":"<code>UiTheme</code>","text":"<pre><code>class UiTheme implements IUiTheme {\n  light: StorytellerTheme;\n  dark: StorytellerTheme;\n  constructor(baseTheme?: Subset&lt;IUiTheme&gt; | null);\n}\n</code></pre> <p>Holds a <code>light</code> and a <code>dark</code> <code>Theme</code>. The constructor builds both from <code>baseTheme</code>, and unset properties keep their defaults. The view's <code>UiStyle</code> decides which theme applies. See Customize themes.</p> <pre><code>const theme = new Storyteller.UiTheme({\n  light: { colors: { primary: '#1C62EB' } },\n  dark: { colors: { primary: '#6699FF' } },\n});\n</code></pre>"},{"location":"reference/types/#theme","title":"<code>Theme</code>","text":"<pre><code>class StorytellerTheme implements IStorytellerTheme {\n  colors: StorytellerColorsTheme;\n  font: string;\n  primitives: StorytellerPrimitivesTheme;\n  lists: StorytellerListsTheme;\n  storyTiles: StorytellerTilesTheme;\n  player: StorytellerPlayerTheme;\n  clipPlayer: StorytellerClipPlayerTheme;\n  buttons: StorytellerButtonsTheme;\n  instructions: StorytellerInstructionsTheme;\n  engagementUnits: StorytellerEngagementUnitsTheme;\n  isDark: boolean;\n  constructor(theme?: Subset&lt;IStorytellerTheme&gt;);\n  toPlainObject(): this;\n}\n</code></pre> <p>Exported as <code>Theme</code>. One color scheme of a theme. The constructor copies the properties of <code>theme</code> over the defaults. The SDK sets <code>isDark</code> when it builds the dark theme. <code>toPlainObject</code> returns the instance.</p> Property Theme section <code>colors</code> Colors <code>font</code> Font <code>primitives</code> Primitives <code>lists</code> Lists <code>storyTiles</code> Story Tiles <code>player</code> Player <code>clipPlayer</code> Clips player <code>buttons</code> Buttons <code>instructions</code> Instructions <code>engagementUnits</code> Polls and Quizzes theme"},{"location":"reference/types/#subset","title":"<code>Subset</code>","text":"<pre><code>type Subset&lt;K&gt; = {\n  [attr in keyof K]?: K[attr] extends object\n    ? Subset&lt;K[attr]&gt;\n    : K[attr] extends object | null\n    ? Subset&lt;K[attr]&gt; | null\n    : K[attr] extends object | null | undefined\n    ? Subset&lt;K[attr]&gt; | null | undefined\n    : K[attr];\n};\n</code></pre> <p>A recursive <code>Partial</code>. Theme inputs use it, so you set only the properties that you change, at any depth.</p> <pre><code>const rowTheme: Storyteller.Subset&lt;Storyteller.UiTheme&gt; = {\n  light: { lists: { row: { startInset: 0 } } },\n};\n</code></pre>"},{"location":"reference/types/#server-rendering","title":"Server rendering","text":"<p>These exports build Story markup for server-side rendering. They do not use <code>window</code> or <code>document</code>.</p>"},{"location":"reference/types/#serverrenderer","title":"<code>ServerRenderer</code>","text":"<pre><code>ServerRenderer.getStories(categories?: string[]): Promise&lt;ServerRenderedStory[]&gt;\nServerRenderer.render(stories: ServerRenderedStory[]): React.JSX.Element\n</code></pre> <p>A singleton instance. <code>getStories</code> loads the Stories of the given categories with the API key from <code>initialize</code>, and keeps the Stories that have a Google Web Story URL. <code>render</code> returns a hidden <code>&lt;amp-story-player&gt;</code> element with a link, poster image, and title for each Story. No task guide covers these methods.</p> Parameter Type Required Default Description <code>categories</code> <code>string[]</code> No <code>[]</code> Story category IDs <code>stories</code> <code>ServerRenderedStory[]</code> Yes None Stories from <code>getStories</code>"},{"location":"reference/types/#serverrenderedstory","title":"<code>ServerRenderedStory</code>","text":"<pre><code>type ServerRenderedStory = {\n  id: string;\n  href: string;\n  title: string;\n  thumbnailUrl: string;\n};\n</code></pre> <p><code>href</code> is the Story's Google Web Story URL.</p>"},{"location":"reference/types/#other-exports","title":"Other exports","text":"<p>The SDK also exports these names. No guide covers them, and integrations do not need them:</p> Export Kind Notes <code>Story</code> Class Story data model from the Stories API. No public SDK method or callback returns it in 11.0.0 <code>QuizRenderer</code> Instance Renders Quiz questions and results inside a Story page document. The SDK's Story page script uses its own copy <code>QuizApiService</code> Instance Loads Quiz data for Story pages. The SDK's Story page script uses its own copy"},{"location":"reference/views/","title":"Views and configuration","text":"<p>A view renders Storyteller content into a container element on your page. This page lists the constructor of each view class, the properties and methods that views share, and the configuration interfaces. For layout and setup tasks, see Choose a view and Configure views.</p>"},{"location":"reference/views/#view-classes","title":"View classes","text":"<p>The SDK exports six view classes:</p> Class Shows Content argument Configuration input Delegate <code>StorytellerStoriesRowView</code> Stories in a horizontal row Optional category IDs <code>IListConfiguration&lt;'StorytellerStoriesRowView'&gt;</code> <code>IListViewDelegate</code> <code>StorytellerStoriesGridView</code> Stories in a grid Optional category IDs <code>IListConfiguration&lt;'StorytellerStoriesGridView'&gt;</code> <code>IListViewDelegate</code> <code>StorytellerClipsRowView</code> Clips in a horizontal row Collection ID <code>IListConfiguration&lt;'StorytellerClipsRowView'&gt;</code> <code>IListViewDelegate</code> <code>StorytellerClipsGridView</code> Clips in a grid Collection ID <code>IListConfiguration&lt;'StorytellerClipsGridView'&gt;</code> <code>IListViewDelegate</code> <code>StorytellerClipsPlayerView</code> A Clips player mounted in the page Collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code> <code>IStorytellerClipsPlayerConfiguration</code> <code>IStorytellerClipsPlayerDelegate</code> <code>StorytellerEmbeddedClipsPlayerView</code> A Clips player that fills a fixed area of the page Collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code> <code>IStorytellerEmbeddedClipsPlayerConfiguration</code> <code>IStorytellerClipsPlayerDelegate</code> <p>Create a view after <code>initialize</code> resolves, and call <code>destroy</code> before your application removes the container.</p>"},{"location":"reference/views/#constructors","title":"Constructors","text":"<p>Each constructor takes the container element ID first. The constructor renders the view and starts loading its content.</p>"},{"location":"reference/views/#storytellerstoriesrowview","title":"<code>StorytellerStoriesRowView</code>","text":"<pre><code>new StorytellerStoriesRowView(\n  elementId: string,\n  listCategories?: string[],\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> Parameter Type Required Default Description <code>elementId</code> <code>string</code> Yes None ID of the container element <code>listCategories</code> <code>string[]</code> No <code>[]</code> Story category IDs. With no categories, the row shows the Stories in the Home list <code>useGoogleWebStoryUrls</code> <code>boolean</code> No <code>false</code> <code>true</code> turns each Story tile into a link to the Story's Google Web Story URL, when the API provides one, instead of opening the SDK player <pre><code>const storyRow = new Storyteller.StorytellerStoriesRowView(\n  'stories-row-id',\n  ['category-id']\n);\n</code></pre> <ul> <li>Guide: Add a Story or Clips row</li> </ul>"},{"location":"reference/views/#storytellerstoriesgridview","title":"<code>StorytellerStoriesGridView</code>","text":"<pre><code>new StorytellerStoriesGridView(\n  elementId: string,\n  listCategories?: string[],\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> <p>The parameters match <code>StorytellerStoriesRowView</code>.</p> <ul> <li>Guide: Add a Story or Clips grid</li> </ul>"},{"location":"reference/views/#storytellerclipsrowview","title":"<code>StorytellerClipsRowView</code>","text":"<pre><code>new StorytellerClipsRowView(\n  elementId: string,\n  collectionName: string,\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> Parameter Type Required Default Description <code>elementId</code> <code>string</code> Yes None ID of the container element <code>collectionName</code> <code>string</code> Yes None Clips collection ID. With an empty ID, the view loads no Clips <code>useGoogleWebStoryUrls</code> <code>boolean</code> No <code>false</code> Accepted for parity with Stories views. It has no effect on Clips <p>The declarations also list a fourth argument, <code>{ deferInitialization?: boolean }</code>. The SDK's player views use it to delay loading. Leave it out: with <code>deferInitialization: true</code>, a row or grid never loads.</p> <pre><code>const clipsRow = new Storyteller.StorytellerClipsRowView(\n  'clips-row-id',\n  'collection-id'\n);\n</code></pre> <ul> <li>Guide: Add a Story or Clips row</li> </ul>"},{"location":"reference/views/#storytellerclipsgridview","title":"<code>StorytellerClipsGridView</code>","text":"<pre><code>new StorytellerClipsGridView(\n  elementId: string,\n  collectionName: string,\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> <p>The parameters match <code>StorytellerClipsRowView</code>.</p> <ul> <li>Guide: Add a Story or Clips grid</li> </ul>"},{"location":"reference/views/#storytellerclipsplayerview","title":"<code>StorytellerClipsPlayerView</code>","text":"<pre><code>new StorytellerClipsPlayerView(\n  elementId: string,\n  source: string | StorytellerClipsPlayerSource,\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> Parameter Type Required Default Description <code>elementId</code> <code>string</code> Yes None ID of the container element <code>source</code> <code>string</code> or <code>StorytellerClipsPlayerSource</code> Yes None A collection ID string, or an object with exactly one of <code>collection</code>, <code>clipId</code>, or <code>externalId</code> <code>useGoogleWebStoryUrls</code> <code>boolean</code> No <code>false</code> Accepted for parity with Stories views. It has no effect on Clips <p><code>StorytellerClipsPlayerSource</code> has three optional fields. Set exactly one of them to a non-empty value:</p> <pre><code>interface StorytellerClipsPlayerSource {\n  collection?: string;\n  clipId?: string;\n  externalId?: string;\n}\n</code></pre> <p>A <code>collection</code> source plays the collection and supports collection navigation. A <code>clipId</code> or <code>externalId</code> source plays one Clip.</p> <p>The constructor throws an <code>Error</code> for an object source with more than one value or with none:</p> Source Error message More than one non-empty field <code>StorytellerClipsPlayerView only supports one source at a time. Provide exactly one of `collection`, `clipId`, or `externalId`.</code> No non-empty field <code>StorytellerClipsPlayerView requires one of `collection`, `clipId`, or `externalId`.</code> <pre><code>const clipPlayer = new Storyteller.StorytellerClipsPlayerView(\n  'clips-player-id',\n  { externalId: 'clip-external-id' }\n);\n</code></pre> <ul> <li>Since: 10.1.0. Single-Clip sources were added in 10.13.6</li> <li>Guide: Clips player initialization</li> </ul>"},{"location":"reference/views/#storytellerembeddedclipsplayerview","title":"<code>StorytellerEmbeddedClipsPlayerView</code>","text":"<pre><code>new StorytellerEmbeddedClipsPlayerView(\n  elementId: string,\n  source: string | StorytellerClipsPlayerSource,\n  useGoogleWebStoryUrls?: boolean\n)\n</code></pre> <p>The class extends <code>StorytellerClipsPlayerView</code>, so its parameters, source rules, errors, and members match that class. It differs in these ways:</p> <ul> <li>The player shows one Clip at a time and fills the container. Size the container with CSS</li> <li>The player does not lock page scrolling. Wheel input over the player stays in the player instead of scrolling the page</li> <li><code>Storyteller.sharedInstance.dismissPlayer</code> does not close it</li> </ul> <p>The embedded player suits a fixed area of your layout, such as a live blog or match centre.</p> <ul> <li>Since: 10.13.7</li> <li>Guide: Add a Clips player to a page</li> </ul>"},{"location":"reference/views/#deprecated-aliases","title":"Deprecated aliases","text":"<p><code>RowView</code> and <code>GridView</code> are deprecated aliases of <code>StorytellerStoriesRowView</code> and <code>StorytellerStoriesGridView</code>. They reference the same classes. Use the full names in new code.</p>"},{"location":"reference/views/#container-element","title":"Container element","text":"<p>The constructors read the container element when you call them:</p> <ul> <li>The element must exist. Otherwise, the SDK logs <code>No element with ID &lt;elementId&gt; was found. The Storyteller view couldn't be initialized.</code> as a console error, and the view renders nothing</li> <li>Use an ID with ASCII letters, numbers, <code>-</code>, and <code>_</code>. An ID that is not a valid CSS selector logs a warning when logging is enabled</li> <li>The SDK adds the <code>storyteller</code> class and a <code>storyteller-view-id</code> attribute to the element</li> </ul> <p>The element can also carry these attributes, which the constructor reads once:</p> Attribute Values Views Effect <code>data-ui-style</code> <code>auto</code>, <code>light</code>, <code>dark</code> All Initial <code>uiStyle</code> <code>data-cell-type</code> <code>round</code>, <code>square</code> <code>StorytellerStoriesRowView</code>, <code>StorytellerClipsRowView</code> Initial tile shape <code>data-base-url</code> A basename All Basename to use when <code>configuration.basename</code> is not set <p>A row fills the height of its container, so give the container a height. See the note in Add a Story or Clips row.</p>"},{"location":"reference/views/#members-of-every-view","title":"Members of every view","text":"<p>Every view class has these members.</p>"},{"location":"reference/views/#configuration","title":"<code>configuration</code>","text":"<pre><code>set configuration(configuration: Partial&lt;ListConfiguration&lt;ViewName&gt;&gt;)\nget configuration(): ListConfiguration&lt;ViewName&gt;\n</code></pre> <p><code>ViewName</code> is the class name, such as <code>'StorytellerStoriesRowView'</code>. The two Clips player classes both use <code>'StorytellerClipsPlayerView'</code>, and their setter takes <code>IStorytellerClipsPlayerConfiguration</code>. <code>ListConfiguration</code> is not exported. Assign an <code>IListConfiguration</code> value instead.</p> <p>Assigning an object updates only the fields that it includes:</p> <ul> <li>A change to <code>categories</code>, <code>collection</code>, <code>clipId</code>, or <code>externalId</code> reloads the view's content</li> <li>A change to <code>theme</code> or <code>uiStyle</code> rebuilds the view theme</li> <li>A <code>displayLimit</code> field set to <code>undefined</code> or <code>0</code> removes the limit</li> <li>A <code>context</code> change applies to later activity events</li> </ul> <p>Reading the property returns the current values, including the view theme that the SDK merged from the global theme and <code>configuration.theme</code>.</p> <pre><code>storyRow.configuration = {\n  categories: ['category-id'],\n  displayLimit: 10,\n  uiStyle: Storyteller.UiStyle.dark,\n};\n</code></pre> <ul> <li>Since: 10.0.0</li> <li>Guide: Configure views</li> </ul>"},{"location":"reference/views/#delegate","title":"<code>delegate</code>","text":"<pre><code>get delegate(): IListViewDelegate\nset delegate(delegateObj: IListViewDelegate)\n</code></pre> <p>The view's callbacks. The Clips player classes use <code>IStorytellerClipsPlayerDelegate</code>. Assigning an object replaces the previous delegate. The SDK fills callbacks that you leave out with no-op functions.</p> <pre><code>storyRow.delegate = {\n  onDataLoadComplete: (success, error, dataCount) =&gt; {\n    const container = document.getElementById('stories-row-id');\n\n    if (container) {\n      container.hidden = !success || dataCount === 0;\n    }\n  },\n};\n</code></pre> <ul> <li>Type: <code>IListViewDelegate</code></li> <li>Guide: Handle view callbacks</li> </ul>"},{"location":"reference/views/#reloaddata","title":"<code>reloadData</code>","text":"<pre><code>reloadData(): Promise&lt;void&gt;\n</code></pre> <p>Loads fresh content for the view from the API. Clips views load the first page again. The view calls <code>onDataLoadStarted</code>, then <code>onDataLoadComplete</code> with the result.</p> <ul> <li>Returns: a promise that resolves after the load finishes. A failed load resolves too and reports the error through <code>onDataLoadComplete</code></li> <li>Guide: reloadData</li> </ul>"},{"location":"reference/views/#destroy","title":"<code>destroy</code>","text":"<pre><code>destroy(): void\n</code></pre> <p>Releases the view. The SDK unmounts the view from the container, removes the view's player container unless another view shares it, and stops theme updates for the view. A second call does nothing. Call <code>destroy</code> before your application removes or replaces the container, such as in a React effect cleanup.</p> <ul> <li>Guides: Use React or Next.js, Troubleshoot page transitions</li> </ul>"},{"location":"reference/views/#deprecated-view-members","title":"Deprecated view members","text":"<p>These members still work in 11.0.0. Replace them with <code>configuration</code> or the shared instance:</p> Member Views Replacement <code>theme</code> (get and set) All <code>configuration.theme</code> <code>uiStyle</code> (get and set) All <code>configuration.uiStyle</code> <code>displayLimit</code> (get and set) All <code>configuration.displayLimit</code> <code>categories</code> (get and set) Stories views <code>configuration.categories</code>. The setter does not reload the view <code>cellType</code> (set) <code>StorytellerStoriesRowView</code> <code>configuration.cellType</code> <code>openStory(id: string): void</code> Stories views <code>Storyteller.sharedInstance.openStory</code> <code>openPage(pageId: string, onError?: (message: string) =&gt; void): void</code> Stories views <code>Storyteller.sharedInstance.openPage</code>"},{"location":"reference/views/#members-of-some-views","title":"Members of some views","text":"<p>These members exist only on the classes listed.</p>"},{"location":"reference/views/#celltype","title":"<code>cellType</code>","text":"<pre><code>set cellType(type: StorytellerListViewCellType)\n</code></pre> <p>Available on <code>StorytellerClipsRowView</code>. Sets the tile shape to <code>CellType.round</code> or <code>CellType.square</code>. The Clips row configuration has no <code>cellType</code> field, so use this setter or the <code>data-cell-type</code> attribute. For <code>StorytellerStoriesRowView</code>, use <code>configuration.cellType</code>.</p> <ul> <li>Guide: cellType</li> </ul>"},{"location":"reference/views/#toplevelbackbuttonenabled","title":"<code>topLevelBackButtonEnabled</code>","text":"<pre><code>get topLevelBackButtonEnabled(): boolean\nset topLevelBackButtonEnabled(isEnabled: boolean)\n</code></pre> <p>Available on <code>StorytellerClipsPlayerView</code> and <code>StorytellerEmbeddedClipsPlayerView</code>. <code>true</code> shows a back button at the top of the player. A tap calls <code>onTopLevelBackTapped</code>, or <code>window.history.back()</code> when the delegate has no such callback. The default is <code>false</code>. This property is not part of <code>configuration</code>.</p> <pre><code>clipPlayer.topLevelBackButtonEnabled = true;\nclipPlayer.delegate = {\n  onTopLevelBackTapped: () =&gt; {\n    window.history.back();\n  },\n};\n</code></pre> <ul> <li>Since: 10.13.6</li> <li>Guide: topLevelBackButtonEnabled</li> </ul>"},{"location":"reference/views/#configuration_1","title":"Configuration","text":"<p>The configuration interfaces describe what you can assign to a view's <code>configuration</code> property.</p>"},{"location":"reference/views/#ilistconfiguration","title":"<code>IListConfiguration</code>","text":"<pre><code>type IListConfiguration&lt;\n  ListType extends keyof ListTypeToConfigMap | void = void\n&gt;\n</code></pre> <p><code>ListTypeToConfigMap</code> is an internal map from each view class name to its fields. Pass a view class name as the type argument to select the fields for that view. Every field is optional:</p> Type argument Fields None <code>basename</code>, <code>context</code>, <code>displayLimit</code>, <code>theme</code>, <code>uiStyle</code> <code>'StorytellerStoriesRowView'</code> The fields for no type argument, plus <code>categories</code>, <code>preload</code>, <code>cellType</code> <code>'StorytellerStoriesGridView'</code> The fields for no type argument, plus <code>categories</code>, <code>preload</code> <code>'StorytellerClipsRowView'</code>, <code>'StorytellerClipsGridView'</code> The fields for no type argument, plus <code>collection</code> <code>'StorytellerClipsPlayerView'</code>, <code>'StorytellerEmbeddedClipsPlayerView'</code> The fields for no type argument, plus <code>collection</code>, <code>clipId</code>, <code>externalId</code> <p>The fields have these types and defaults:</p> Field Type Views Default Description <code>basename</code> <code>string</code> All <code>stories</code> or <code>clips</code>. With several views on a page, a value derived from the categories or collection First segment of the player hash URL. The SDK keeps only ASCII letters, numbers, <code>-</code>, and <code>_</code> <code>categories</code> <code>string[]</code> Stories views The constructor <code>listCategories</code> Story category IDs <code>cellType</code> <code>CellType</code> <code>StorytellerStoriesRowView</code> <code>CellType.square</code>, or the <code>data-cell-type</code> attribute Tile shape <code>collection</code> <code>string</code> Clips views The constructor collection Clips collection ID <code>clipId</code> <code>string</code> Clips players None Clip ID for single-Clip playback <code>externalId</code> <code>string</code> Clips players None Clip external ID for single-Clip playback <code>context</code> <code>unknown</code> All <code>undefined</code> Your attribution data. The SDK returns it in <code>UserActivityData.context</code> <code>displayLimit</code> <code>number</code> Rows and grids. The player types accept it too No limit Maximum number of tiles <code>preload</code> <code>boolean</code> Stories views <code>false</code> <code>true</code> starts more Story player work before the first open. Assigning <code>false</code> later does not undo <code>true</code> <code>theme</code> <code>Subset&lt;UiTheme&gt;</code> All The global theme View theme. The SDK merges it over <code>Storyteller.sharedInstance.theme</code> <code>uiStyle</code> <code>UiStyle</code> All <code>UiStyle.auto</code>, or the <code>data-ui-style</code> attribute Light, dark, or system color scheme <pre><code>type RowConfiguration =\n  Storyteller.IListConfiguration&lt;'StorytellerStoriesRowView'&gt;;\n\nconst rowConfiguration: RowConfiguration = {\n  basename: 'top-stories',\n  cellType: Storyteller.CellType.round,\n  context: { location: 'home' },\n};\n\nstoryRow.configuration = rowConfiguration;\n</code></pre> <ul> <li>Since: 10.0.0. <code>context</code> was added in 10.13.17</li> <li>Guide: Configure views</li> </ul>"},{"location":"reference/views/#clips-player-configuration-types","title":"Clips player configuration types","text":"<pre><code>type IStorytellerClipsPlayerConfiguration =\n  Partial&lt;StorytellerClipsPlayerConfiguration&gt;;\n\ntype IStorytellerEmbeddedClipsPlayerConfiguration =\n  Partial&lt;StorytellerClipsPlayerConfiguration&gt;;\n</code></pre> <p>Both types have the same fields as <code>IListConfiguration&lt;'StorytellerClipsPlayerView'&gt;</code>: <code>basename</code>, <code>context</code>, <code>displayLimit</code>, <code>theme</code>, <code>uiStyle</code>, <code>collection</code>, <code>clipId</code>, and <code>externalId</code>. Their <code>theme</code> field also accepts a full <code>IUiTheme</code>.</p> <p>An update that includes a source field changes the source. Include exactly one non-empty source field. Otherwise, the SDK logs an error and keeps the current source.</p> <pre><code>clipPlayer.configuration = {\n  externalId: 'new-clip-external-id',\n};\n</code></pre> <ul> <li>Guides: Clips player configuration, Embedded Clips player configuration</li> </ul>"},{"location":"views/","title":"Choose a view","text":"<p>A view is an SDK object that renders Storyteller content into an element on your page. Choose the view that matches the content and layout you need, then follow its guide.</p> Goal View Content source Show Stories in a horizontal row <code>StorytellerStoriesRowView</code> Optional Category IDs Show Stories in a grid <code>StorytellerStoriesGridView</code> Optional Category IDs Show Clips in a horizontal row <code>StorytellerClipsRowView</code> Collection ID Show Clips in a grid <code>StorytellerClipsGridView</code> Collection ID Play Clips in an area of the page set aside for Clips <code>StorytellerClipsPlayerView</code> Collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code> Play Clips inside other page content, such as a live blog <code>StorytellerEmbeddedClipsPlayerView</code> Collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code> <p>Every view constructor takes these arguments:</p> <ul> <li><code>elementId</code>: the ID of the element the view renders into</li> <li><code>categories</code> (Stories views, optional): Category IDs. Without them, the view shows the Stories in your Home list.</li> <li><code>collectionId</code> (Clips rows and grids): the collection ID</li> <li><code>source</code> (Clips player views): a collection ID, <code>{ clipId }</code>, or <code>{ externalId }</code>. The constructor throws an <code>Error</code> if you pass no source or more than one.</li> </ul> <p>The API reference lists the full constructor signatures.</p>"},{"location":"views/#rows","title":"Rows","text":"<p>Use a row for a compact list that users scroll horizontally. Rows can show round or square tiles through <code>cellType</code>. Grids don't use <code>cellType</code>.</p> <p>Add a Story or Clips row</p>"},{"location":"views/#grids","title":"Grids","text":"<p>Use a grid when the page should show more tiles at once. Grids use the same settings as the other views.</p> <p>Add a Story or Clips grid</p>"},{"location":"views/#open-clips-from-a-custom-control","title":"Open a player from your code","text":"<p>To open a Story or Clips player from a button, link, or route in your application, call a method on <code>Storyteller.sharedInstance</code>, such as <code>openStory</code>, <code>openCollection</code>, or <code>openClipByExternalId</code>.</p> <p>Open a player programmatically</p>"},{"location":"views/#embedded-clips-player","title":"Clips players","text":"<p>Both Clips player views render the Clips player into your container. <code>StorytellerEmbeddedClipsPlayerView</code> shows one Clip at a time, lets the rest of the page scroll, and ignores <code>Storyteller.sharedInstance.dismissPlayer</code>. <code>StorytellerClipsPlayerView</code> uses the full Clips player layout, which can show neighboring Clips on wide screens, and locks page scrolling while it's shown.</p> <p>Add a Clips player to a page</p>"},{"location":"views/#polls-and-quizzes","title":"Polls and Quizzes","text":"<p>Polls and Quizzes are Story Pages: Pages inside a Story. Show the Story in a Stories row or grid, and the Story player handles the Poll or Quiz.</p> <p>Show Polls and Quizzes</p>"},{"location":"views/#shared-list-configuration","title":"Settings shared by all views","text":"<p>All views share settings for content, themes, display limits, preload behavior, analytics context, and delegates.</p> <p>Configure views</p>"},{"location":"views/engagement/","title":"Show Polls and Quizzes","text":"<p>Polls and Quizzes are Story Pages: Pages inside a Story that ask the user a question. Publish a Story that contains a Poll or Quiz Page, then show the Story in a Stories row or grid. The Story player handles the interaction, so you don't write any code for it.</p>"},{"location":"views/engagement/#poll-results","title":"Poll results","text":"<p>After a user votes, the Poll stays on screen and shows the percentage for each answer. The results stay visible after the first vote. A later tap can move to the next Page or Story.</p>"},{"location":"views/engagement/#answer-text","title":"Answer text","text":"<p>Poll and Quiz answers can show up to two lines. Longer text is cut off. Check the published answer text at the screen widths your users have.</p>"},{"location":"views/engagement/#appearance-and-analytics","title":"Appearance and analytics","text":"<p>Use the Poll and Quiz theme settings to style the answers. Handle votes and Quiz answers in the <code>onUserActivityOccurred</code> callback, then check the Poll events and Quiz events for their data fields.</p> <p>If you are moving from a 10.13.x integration, include long answer text in your version 11 checks.</p>"}]}