# Storyteller React Native SDK Public Docs (AI bundle) This is a core, aggregated bundle of Storyteller React Native SDK public documentation for LLM agents. For full per-page references (including the complete source Markdown), use the per-page exports in `public-docs/ai/llms-*.txt`. Notes: - This aggregate bundle intentionally excludes `Analytics`, `Changelog`, and `OpenSourceLicenses` to keep the core context smaller. - Use `public-docs/ai/llms-analytics.txt`, `public-docs/ai/llms-changelog.txt`, and `public-docs/ai/llms-open-source-licenses.txt` when needed. # Quickstart Guide URL: /getting-started/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-index` - Source: `public-docs/getting-started/index.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `react-native-new-arch.md`, `react-native-legacy.md`, `expo.md`, `migration-v10-to-v11.md`, `migration-v11-0-to-v11-2.md` ## Overview - Landing page that routes you to the correct install guide based on whether your project uses the New Architecture, Legacy Architecture, or Expo. - Highlights the recommended upgrade path: new apps should use the current 12.x SDK with New Architecture and check v12 host requirements, while existing v10.x apps should review compatibility before switching. - Points Legacy teams or Expo users to the matching setup article and links v10→v11, v11.0→v11.2 and v11→v12 migration guides. - Collects integration and version-specific migration guides in one place for quick navigation. ## When To Use - You need to decide which Storyteller installation instructions match your React Native or Expo project. - You are planning a v10.x → v11.0.0+ upgrade and want to confirm whether migration is required. ## Integration Steps 1. Identify whether your app ships with React Native New Architecture, Legacy Architecture, or Expo tooling. 1. Open the matching guide (`react-native-new-arch.md`, `react-native-legacy.md`, or `expo.md`) and follow its platform-specific install steps. 1. If you are upgrading from v10.x, read `migration-v10-to-v11.md` (and `migration-v11-0-to-v11-2.md` when moving from v11.0.x) before modifying native or JS code. For v12, review `migration-v11-to-v12.md`; the package minimums are Android API 24 and iOS 15.1. ## API Cheat Sheet - `No runtime SDK APIs.` Refer to the architecture-specific guides for setup commands and component props. ## Examples - Use the linked New Architecture, Legacy, Expo, or Migration guides for complete code samples and configuration snippets. ## Pitfalls / Notes - Confirm your React Native version supports the New Architecture before following the v11.0.0+ instructions. - Do not mix installation steps from multiple guides; each assumes a specific architecture and tooling stack. ## Cross-References - public-docs/getting-started/react-native-new-arch.md (v11.0.0+ install) - public-docs/getting-started/react-native-legacy.md (v10.x install) - public-docs/getting-started/expo.md (Expo plugin path) - public-docs/getting-started/migration-v10-to-v11.md (v10 → v11 migration) - public-docs/getting-started/migration-v11-0-to-v11-2.md (v11.0 → v11.2 migration) # React Native with New Architecture (v11.0.0+) URL: /getting-started/react-native-new-arch/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-react-native-new-arch` - Source: `public-docs/getting-started/react-native-new-arch.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `../Storyteller.md`, `../Themes.md`, `../Analytics.md`, `../Ads.md`, `../UserCustomization.md`, `../getting-started/migration-v10-to-v11.md` ## Overview - Covers installing Storyteller SDK v11.0.0+ on React Native New Architecture projects (RN ≥0.76 enables it by default). - Explains how to confirm `newArchEnabled=true` in `android/gradle.properties` and `ENV['RCT_NEW_ARCH_ENABLED']='1'` in `ios/Podfile`. - Documents npm/yarn installation plus Maven Central and iOS CocoaPods sources, including the Storyteller Lottie podspec source required by current iOS SDKs. - Provides a complete initialization-to-first-Stories-row example with shared initialization attempts, retry UI, bounded row height and data-load success/empty/error handling. - Points to next-step docs (components, theming, analytics, user attributes, ads) after setup. ## When To Use - You are onboarding Storyteller SDK v11.0.0+ into a New Architecture React Native app or have already migrated from v10.x. - You need the authoritative list of native repo sources and initialization steps for New Architecture builds. ## Integration Steps 1. For the current 12.x SDK, check the v12 Android host requirements and package minimums (API 24, iOS 15.1), then ensure the New Architecture flags are enabled on both platforms (`newArchEnabled=true`, `ENV['RCT_NEW_ARCH_ENABLED']='1'`). 1. Install `@getstoryteller/react-native-storyteller-sdk` and make sure Maven Central plus CocoaPods sources are configured as shown. 1. Run `pod install` (and the equivalent Android sync) and call the promise-based `StorytellerSdk.initialize` before rendering Storyteller components. ## API Cheat Sheet - `StorytellerSdk.initialize(apiKey, externalId?)` — Promise that confirms native SDK initialization succeeds. - v11 components emit typed events (`DataLoadCompletedEvent`, etc.); reference component docs for full prop contracts. ## Examples - The complete TSX App mounts content after initialization, requests row data through a ref and distinguishes initialization failure from list-load failure. - Next Steps list directs you to components, theming, analytics, user customization, and ads configuration guides. ## Pitfalls / Notes - Missing Maven Central or either Storyteller CocoaPods source will cause Gradle/Pods to fail during install. - Await initialization before mounting content. List load callbacks report content results; they do not prove video playback or player presentation. Rows and scrollable grids need a height. ## Cross-References - public-docs/Storyteller.md (component + API reference post-initialization) - public-docs/getting-started/migration-v10-to-v11.md (steps to reach this state from v10.x) - public-docs/Themes.md, public-docs/Analytics.md, public-docs/UserCustomization.md, public-docs/Ads.md (next-step topics highlighted in the guide) # React Native with Legacy Architecture (v10.x and below) URL: /getting-started/react-native-legacy/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-react-native-legacy` - Source: `public-docs/getting-started/react-native-legacy.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `../Storyteller.md`, `../Themes.md`, `../Analytics.md`, `../Ads.md`, `../UserCustomization.md`, `migration-v10-to-v11.md` ## Overview - Targets Storyteller SDK v10.x, which requires React Native Legacy Architecture; you must explicitly set `newArchEnabled=false` (Android) and `ENV['RCT_NEW_ARCH_ENABLED']='0'` (iOS), on RN 0.76–0.81 where the New Architecture defaults to on. RN 0.82+ cannot enable the Legacy Architecture. - Shows how to install `@getstoryteller/react-native-storyteller-sdk@^10.8.2` via npm or yarn. - Details Android repo configuration (`storyteller.mycloudrepo.io`) and iOS Podfile sources (`storyteller-sdk-ios-podspec`) needed for native dependencies. - Provides callback-based SDK initialization sample demonstrating result handling and logging. - Lists follow-up docs for components, theming, analytics, user customization, ads, and the migration path to v11. ## When To Use - Your app must stay on Storyteller v10.x (Legacy Architecture) due to platform constraints. - You need the precise native repo settings and initialization pattern for callback-based APIs. ## Integration Steps 1. Disable the New Architecture in `android/gradle.properties` and `ios/Podfile` (`newArchEnabled=false`, `ENV['RCT_NEW_ARCH_ENABLED']='0'`). 1. Install the SDK with npm/yarn, add the Storyteller Maven repository to `android/build.gradle`, and add both CocoaPods sources to `ios/Podfile`. 1. The historical 10.8.2 package declares RN ≥0.63.0. Run `pod install` and rebuild; then initialize the SDK with `StorytellerSdk.initialize({ apiKey, externalId }, callback)` before rendering Storyteller components. ## API Cheat Sheet - `StorytellerSdk.initialize(config, callback)` — callback receives `{ result, message }`; required before using any Storyteller components on v10.x. - Callback-style component props (`onDataLoadCompleted(isSuccessful, error, dataCount)`) remain in v10.x; upgrade to v11 to use typed event objects. ## Examples - Initialization snippet logs successful/failed setup based on the callback payload. - Next Steps section links directly to components, theming, analytics, user customization, and ads docs for deeper examples. ## Pitfalls / Notes - React Native 0.76–0.81 enables the New Architecture by default; disable it for v10. RN 0.82+ cannot run this Legacy Architecture integration. - Missing the Storyteller Maven repository or Podfile sources results in unresolved native dependencies during build. - SDK APIs stay callback-based; mixing promise-style code will not work until you migrate to v11. ## Cross-References - public-docs/Storyteller.md (component + API reference once initialized) - public-docs/getting-started/migration-v10-to-v11.md (path to v11 when you are ready) - public-docs/Themes.md, public-docs/Analytics.md, public-docs/UserCustomization.md, public-docs/Ads.md (areas highlighted in “Next Steps”) # Using Storyteller SDK with Expo URL: /getting-started/expo/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-expo` - Source: `public-docs/getting-started/expo.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `../getting-started/react-native-new-arch.md`, `../getting-started/react-native-legacy.md`, `../getting-started/migration-v10-to-v11.md`, `../getting-started/migration-v11-0-to-v11-2.md` ## Overview - Storyteller requires a native development or production build; Expo Go does not include its native modules. v11+ requires the New Architecture, while the historical v10.8.2 package requires a host that still supports the Legacy Architecture. - Provides npm/yarn install commands for the SDK and shows how to register the `@getstoryteller/react-native-storyteller-sdk` config plugin. - Distinguishes Expo SDK 52 opt-in for existing apps, SDK 53/54 defaults and SDK 55+ mandatory New Architecture. The Storyteller config plugin changes iOS CocoaPods configuration; Android host requirements remain separate. - Walks through rebuilding the native development client via `expo prebuild --clean`, `expo run:ios`, and `expo run:android` after toggling architecture. - Guides existing Expo apps upgrading from ≤11.0.5 to remove the autolinking exclusion added by older plugin versions. - Includes troubleshooting for Expo SDK 52 Gradle codegen dependency errors and recommends upgrading to Expo 53+. ## When To Use - You are integrating Storyteller inside an Expo-managed workflow instead of a bare React Native app. - You need to choose an architecture-compatible historical or current SDK version and rebuild Expo native projects after configuration changes. ## Integration Steps 1. Pick the SDK version based on your Expo SDK and desired architecture (v11+ with New Architecture enabled; v10.x with it disabled). 1. `npm install`/`yarn add @getstoryteller/react-native-storyteller-sdk` and add the plugin entry to `app.json`/`app.config.js`. 1. For Expo SDK 52–54, configure `newArchEnabled` for the selected Storyteller version. SDK 55+ always uses the New Architecture and cannot host v10.x. Apply the v12 Android migration requirements when installing RN SDK 12, then run `npx expo prebuild --clean` and rebuild with `npx expo run:ios` or `npx expo run:android`. 1. If upgrading from ≤11.0.5, remove any `expoAutolinking.exclude` line that references the Storyteller package and regenerate native projects. ## API Cheat Sheet - `"plugins": ["@getstoryteller/react-native-storyteller-sdk"]` — registers the plugin that adds the iOS CocoaPods sources and core native SDK version. - `newArchEnabled` (root/ios/android on applicable Expo releases) — use `true` for v11+ or `false` for historical v10.x; SDK 55+ removes the opt-out. - `npx expo prebuild --clean` / `npx expo run:ios|android` — rerun after changing architecture flags or removing autolinking exclusions to regenerate native code. ## Examples - JSON snippets show the plugin entry and architecture flags for Expo versions that expose those settings. - Upgrade checklist demonstrates how to delete the `expoAutolinking.exclude` line in `android/settings.gradle` and rebuild. ## Pitfalls / Notes - Expo SDK 52 suffers from Gradle codegen dependency errors with New Architecture; upgrade to Expo 53+ whenever possible. - Forgetting to clean/prebuild after toggling `newArchEnabled` leaves stale native artifacts and can crash at runtime. - Plugins through Storyteller 11.0.5 added an Android autolinking exclusion. Use 11.0.6 or later and remove stale exclusions while keeping the SDK version selected for your app. ## Cross-References - public-docs/getting-started/react-native-new-arch.md (detailed new-architecture steps referenced here) - public-docs/getting-started/react-native-legacy.md (Legacy Architecture background for v10.x) - public-docs/getting-started/migration-v10-to-v11.md (planning upgrades from v10.x to v11.0.0+) - public-docs/getting-started/migration-v11-0-to-v11-2.md (planning upgrades from v11.0.x to newer releases) # Migration Guide: v10.x to v11.0.0+ URL: /getting-started/migration-v10-to-v11/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-migration-v10-to-v11` - Source: `public-docs/getting-started/migration-v10-to-v11.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `react-native-new-arch.md`, `react-native-legacy.md`, `Storyteller.md`, `Deeplinking.md`, `UserCustomization.md` ## Overview - Summarizes the major v11 changes: React Native New Architecture requirement, promise-based APIs, reorganized imports, and stronger TypeScript types. - Step-by-step instructions cover upgrading the npm package, enabling New Architecture in `gradle.properties`/`Podfile`, adding required Storyteller CocoaPods sources, cleaning builds, and reinstalling dependencies. - Provides side-by-side code samples showing how initialization, components, navigation methods, custom attributes, and deeplink helpers change between v10 callbacks and v11 promises. - Notes the support contact for migration blockers. ## When To Use - You currently ship v10.x (Legacy Architecture) and need to move to v11.0.0+. - You must audit code for callback-based Storyteller APIs that must be rewritten with promise syntax. ## Integration Steps 1. Select the v11 release line with `@^11.0.0` for this migration. If selecting v12 instead, apply its separate Android host requirements and version-specific native coordinates. 1. Enable New Architecture (`newArchEnabled=true`, `ENV['RCT_NEW_ARCH_ENABLED']='1'`), add the Storyteller SDK and Lottie CocoaPods sources, and rebuild native projects after cleaning Gradle, Pods, node_modules, and Metro cache. 1. Replace callback-style initialization and component props with the v11 promise/typed signatures shown in the examples. 1. Update navigation, custom-attribute, and deeplink helper calls to their new async counterparts, then retest on both platforms. ## API Cheat Sheet - `StorytellerSdk.initialize(apiKey, externalId?)` — Promise-based initializer replacing the old callback pattern. - `StorytellerSdk.openStory(id)` / other navigation helpers — now awaitable Promises; remove callback arguments. - `StorytellerSdk.setCustomAttribute(key, value)` + `StorytellerSdk.customAttributes()` — synchronous setter plus async getter replacing callback forms. - `StorytellerSdk.isStorytellerDeeplink(url)` / `StorytellerSdk.openDeeplink(url)` — synchronous boolean check plus Promise-based opener (callbacks only exist on v10). ## Examples - Initialization snippets illustrate the move from class-based callback initialization to `await StorytellerSdk.initialize`. - Component examples show the new typed event objects (`DataLoadCompletedEvent`) versus positional callback args. - Navigation/custom attribute/deeplink blocks provide direct before/after comparisons to guide refactors. ## Pitfalls / Notes - The v10 `openStory` callback reports an error; it is not a boolean success callback. Historical callback examples are checked against 10.8.2. - Forgetting to clean Gradle, Pods, and Metro cache after enabling New Architecture can leave projects stuck on the old architecture. - All callbacks that previously returned booleans or results must be rewritten as Promises; leaving callbacks in place will cause type and runtime errors. - Update both Android and iOS toggles; enabling the New Architecture on only one platform leads to divergent builds. - Missing the Storyteller Lottie CocoaPods source can prevent current iOS SDK pods from resolving. ## Cross-References - public-docs/getting-started/react-native-new-arch.md (detailed steps for enabling New Architecture) - public-docs/Storyteller.md (full API reference once migrated) - public-docs/Deeplinking.md and public-docs/UserCustomization.md (APIs showcased in the migration examples) # Migration Guide: v11.0 to v11.2 URL: /getting-started/migration-v11-0-to-v11-2/ ## Metadata - Slug: `getting-started-migration-v11-0-to-v11-2` - Source: `public-docs/getting-started/migration-v11-0-to-v11-2.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` ## Overview This guide covers the React Native API changes between `11.0.x` and `11.2.0`. The source compares the `11.0.10` and `11.2.0` tags. It includes the migration steps and code examples for these versions. # Migrating from v11 to v12 URL: /getting-started/migration-v11-to-v12/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `getting-started-migration-v11-to-v12` - Source: `public-docs/getting-started/migration-v11-to-v12.md` - Audience: React Native SDK integrators - Platforms: `Android`, `iOS` - Related: `Ads.md`, `Themes.md`, `Analytics.md` ## Overview - Native versions depend on the installed RN 12 release: RN 12.0.1 uses Android 12.0.1 and iOS 11.7.0, RN 12.0.2 uses Android 12.0.2 and iOS 11.7.1, and RN 12.1.1 uses Android 12.1.1 and iOS 11.8.0. IMA remains Android-only. - Android uses Kotlin 2.1.0 and Compose BOM 2026.06.01; the RN minimum Android API remains 24. - iOS VAST setup preserves an existing GAM or AdMob module; explicitly disable the Google ads module if the host needs the earlier replacement behaviour. ## Integration Steps 1. Update host Kotlin overrides to 2.1.0. If the host uses Compose directly, match its Compose compiler plugin to Kotlin and align the Compose BOM. 2. Remove old root sdkVersion overrides or match them to the native version selected by your RN release. Use mavenCentral() and google(); the shown 12.1.1 coordinates apply to RN 12.1.1, not to earlier RN releases such as 12.0.2. 3. Keep the existing optional ads configuration. This upgrade does not require an ads24 or adsnextgen migration; GAM uses classic Google Mobile Ads 23.4.0. 4. For iOS, call disableGoogleAdsModule() before setupVASTModule or setupGAMVASTModule if the app needs VAST setup to remove an existing GAM/AdMob module. 5. Rebuild and check Stories, Search, full-screen and Embedded Clips, callbacks, installed ads modules, Clips scrubbing and link opening. ## Pitfalls / Notes - Native versions differ between Android and iOS; use the versions documented for the intended RN release instead of forcing them to match. - Do not add an old kotlinCompilerExtensionVersion workaround. Use a JDK supported by the chosen Gradle version; CI uses JDK 17. - Preserve the host target SDK policy independently of minimum API and compile SDK settings. - Local native artifacts used during development are temporary and are not released package requirements. ## Cross-References - public-docs/Ads.md - public-docs/Themes.md - public-docs/Analytics.md # Showcase Apps URL: /Showcase/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `showcase` - Source: `public-docs/Showcase.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `getting-started/expo.md` ## Overview - Highlights the official Storyteller Showcase repository (`getstoryteller/storyteller-showcase-react-native`) with full-featured sample screens. - Notes that the repo includes both the standard React Native showcase and an Expo showcase to demonstrate Expo integration. - Lists environment requirements: the selected sample’s Node version, Yarn, Xcode/iOS SDK, Android SDK/emulator. - Mentions that organization-specific configuration (API keys, environments) must be provided before running. ## When To Use - You need a working reference implementation of Storyteller components, layouts, and configuration patterns. - You want to validate Expo-specific behavior using the provided Expo showcase. ## Integration Steps 1. Clone `https://github.com/getstoryteller/storyteller-showcase-react-native` and install dependencies per its README. 1. Configure required Storyteller API keys or environments for your organization. 1. Run the native or Expo showcase apps with the documented steps to observe components in action. ## API Cheat Sheet - `No runtime SDK APIs.` Consult the showcase repository for concrete component APIs. ## Examples - The Showcase app itself serves as the example for every supported component, theme, and configuration path. ## Pitfalls / Notes - Sample-specific React Native/Expo toolchains do not set the SDK package minimums. Match installed published SDK versions to documented feature applicability; unreleased examples need their unreleased package interface. - Expo Go does not include Storyteller native modules; use a rebuilt development or production app. - Without valid Storyteller credentials, the showcase cannot load content; coordinate with your Storyteller contact. ## Cross-References - public-docs/Storyteller.md (component APIs mirrored in the showcase) - public-docs/getting-started/expo.md (Expo-specific setup referenced by the Expo showcase) # Working with Users URL: /Users/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `users` - Source: `public-docs/Users.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `UserCustomization.md` ## Overview - With default tracking options Storyteller persists a guest identity when `externalId` is null/omitted and reuses it on anonymous initialization. Pass a stable ID for a signed-in user. - Initialization is promise-based in v11+ (callback in v10); identity changes reset per-user state under default tracking; persistence and remote state depend on tracking options. - `StorytellerSdk.setLocale(locale | null)` lets you localize Storyteller UI/content per user via ISO language codes or clear the locale with `null`. - Utility getters (`currentApiKey()`, `isInitialized()`) expose current SDK configuration for diagnostics. - Reinitializing with different IDs supports login/logout flows but requires careful sequencing to avoid concurrent initialize calls. ## When To Use - You need to tie Storyteller consumption analytics to your own user IDs or support logout/login flows. - You must localize Storyteller content based on the app’s language settings. ## Integration Steps 1. Collect or generate a stable user GUID and call `await StorytellerSdk.initialize(apiKey, externalId)` as soon as the ID is known; avoid parallel initialize calls. 1. When a user logs out/logs in, re-run `initialize` with the new `externalId` (or `null` for anonymous) then apply attributes, locale and app-managed follows before reloading content. 1. Set the locale immediately after initialization (`StorytellerSdk.setLocale('fr')`) so requests fetch localized content. 1. Optionally read `StorytellerSdk.currentApiKey()` and `StorytellerSdk.isInitialized()` to confirm state during troubleshooting. ## API Cheat Sheet - `StorytellerSdk.initialize(apiKey, externalId?)` — asynchronous setup; serialize identity changes and reapply settings afterward. - `StorytellerSdk.setLocale(locale | null)` — use a supported ISO language code such as `fr`; iOS ignores unsupported codes, including regional tags. Pass `null` to clear. - `StorytellerSdk.currentApiKey()` — returns the API key currently in use. - `StorytellerSdk.isInitialized()` — boolean indicating initialization status. ## Examples - v11 example shows `try/catch` around `await StorytellerSdk.initialize('api-key', 'user-guid')`; v10 example demonstrates the callback signature. - Locale snippet uses `fr` and clears the preference with `null`. - Reinitialization example returns to the SDK-managed guest identity on logout; a later login uses the new stable ID. ## Pitfalls / Notes - Do not use mutable identifiers (emails) as `externalId`; pick non-changing IDs like GUIDs. - Never call `initialize` concurrently; wait for the Promise to resolve/reject before retrying. - Default-config identity changes reset per-user local state; they do not delete remote activity or accounts. Await each initialization Promise rather than treating `isInitialized()` as a user-switch completion signal. ## Cross-References - public-docs/Storyteller.md (core initialization + API usage) - public-docs/UserCustomization.md (custom attributes and followable categories tied to the current user) # Configuring Storyteller URL: /Storyteller/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `storyteller` - Source: `public-docs/Storyteller.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Ads.md`, `Analytics.md`, `Deeplinking.md`, `Themes.md`, `UserCustomization.md`, `Users.md` ## Overview - `mute()` and `unmute()` return `Promise` on both platforms. Await initialization and mute before presentation for silent first playback; runtime commands preserve playback and ordinary user/device/persistence behavior. Incomplete initialization rejects with `SDK_NOT_INITIALIZED`. - Await `StorytellerSdk.initialize(apiKey, externalId?, eventTrackingOptions?)` before mounting or opening content. Subscribe to events early; status getters can observe setup. `version()` returns the platform native SDK version, not the npm package version. - Global configuration APIs include `setTheme`, nullable `setLocale`, and deep-link openers (`openStory`, `openStoryByExternalId`, `openPage`, `openCategory`, `openCollection`, `openClipByExternalId`, `openCollectionByExternalId`). - Search helpers `openSearch` and `isSearchEnabled` control whether to show search UI; `openSheet` and `openCollectionWithCategory` open other CMS-defined experiences. - Utility methods such as `getStoriesCount`, `getClipsCount`, `getClipsCountForCategories`, `preloadClips`, `dismissPlayer`, `resumePlayer`, and `setUseCustomShareHandling` support UI badges, Android preloading, player control, and app-managed share flows. - Event emitters include `onPlayerOpenFailed` for late Android programmatic Clips-open errors alongside analytics, navigation, sharing, follow, and custom-ad events. ## When To Use - You are wiring up Storyteller’s core SDK initialization, global configuration, deep links, and helper APIs used across list/card/home components. - You need to subscribe to engagement events or adjust tracking behavior for privacy requirements. ## Integration Steps 1. Initialize the SDK early (e.g., App.tsx) with `await StorytellerSdk.initialize(apiKey, externalId?, eventTrackingOptions?)`; use the Promise for completion, including user switches. 1. Configure global appearance/localization by calling `StorytellerSdk.setTheme(theme)` and `StorytellerSdk.setLocale(locale | null)` before rendering Storyteller views. 1. Use the deep-link helpers (`openStory`, `openCollection`, `openClipByExternalId`, `openSearch`, `openSheet`, etc.) to launch content outside of list components; guard with the relevant IDs. 1. Subscribe to events (`onUserActivityOccurred`, `userNavigatedToApp`, `shareButtonTapped`, `categoryFollowActionTaken`, `onPlayerOpenFailed`, `getAdsForList`) and clean up subscriptions when components unmount. ## API Cheat Sheet - `StorytellerSdk.initialize(apiKey, externalId?, eventTrackingOptions?)` — Promise confirming initialization succeeds; await before mounting or opening content. - `StorytellerSdk.setTheme(theme)` / `setLocale(locale | null)` — set global theming and localization defaults; pass `null` to clear locale. - `StorytellerSdk.openStory(id, openReason?)`, `openStoryByExternalId(externalId, openReason?)`, `openPage(id, openReason?)`, `openCategory(category, openReason?)`, `openCollection(id, clipId?, openReason?, adConfiguration?)`, `openClipByExternalId(collectionId, externalId, openReason?)`, `openCollectionByExternalId(collectionId, externalId, openReason?)` — open specific content experiences. - `StorytellerSdk.openSearch()` / `isSearchEnabled()` — launch Storyteller search if the tenant supports it. - `StorytellerSdk.getStoriesCount(categoryIds[])` counts Stories. `getClipsCount(string)` counts an iOS collection but an Android category; arrays and `getClipsCountForCategories(categoryIds[])` are Android-only category counts. They are not a portable collection-count API. - `StorytellerSdk.dismissPlayer(animated, reason)` / `resumePlayer()` — control the player lifecycle. - `StorytellerSdk.setUseCustomShareHandling(enabled)` / `shareButtonTapped(listener)` — let the host app present a custom share flow, then call `resumePlayer()` after dismissal. - `StorytellerSdk.preloadClips(collectionId, clipIds?, preloadVideos?)` / `cancelPreloadClips(handle)` — Android Clips preloading helpers; iOS resolves `null` and treats cancel as a no-op. - `StorytellerSdk.setFollowedCategories(categories): Promise` — replaces resolvable app-managed follows; SDK-managed following makes it a no-op, as does disabled personalization on Android. - `StorytellerSdk.onPlayerOpenFailed(listener)` — observes asynchronous Android programmatic Clips-open failures after native accepted the request; iOS reports the corresponding failure by rejecting the method Promise. - `StorytellerClipsAdConfiguration` — optional `preRollEnabled` and `bottomBannerEnabled` flags plus Android-only `betweenClipsAdProviderOrder`; `null` preserves native order, `[]` disables standard between-Clips ads, and a populated array sets the allowlist/fallback order. - `StorytellerFollowableCategories`, `StorytellerFollowableCategory`, `StorytellerFollowableCategoryPlacement`, and `ShareButtonTappedEvent` — exported types for category catalogs and app-managed sharing. - `StorytellerSdk.eventTrackingOptions()` — read tracking/privacy configuration. Derive its options type from the initialize parameter; the exported `StorytellerEventTrackingOptions` currently uses a different `disabledFeatures` enum and is not directly assignable to initialize. ## Examples - Initialization snippet shows promise-based `try/catch` usage replacing the legacy callback API. - Deep-link examples demonstrate guarding with `isPresentingContent()` and invoking `openStory` or `openCollection`. - Search, sheet, and collection helpers include Promise-based `await` patterns; event sections show React hook patterns for analytics and navigation callbacks. ## Pitfalls / Notes - Await initialization before content; getters and subscriptions can be used during setup. `isInitialized()` is not a completion signal for a new user-switch attempt. - Always remove event subscriptions (`subscription.remove()`) on unmount to prevent leaks. - Provide valid IDs and handle rejection. Android open Promises resolve after native invocation; late non-Clips open errors have no dedicated RN failure event. Programmatic Clips errors use `onPlayerOpenFailed`. - Tracking options are read-only after initialization in the linked native SDKs; reinitialize with new options when privacy choices change. - `isPlayerMuted()` is iOS-only for the linked native versions and rejects on Android; Clips preloading similarly has no iOS native implementation. - Cross-platform programmatic Clips-open callers should handle Promise rejection for iOS and subscribe to `onPlayerOpenFailed` for late Android failures. ## Cross-References - public-docs/Ads.md (GAM + Storyteller ad workflows referenced by `getAdsForList`) - public-docs/Analytics.md (details for events delivered via `onUserActivityOccurred`) - public-docs/Deeplinking.md (handling incoming URLs and navigation callbacks) - public-docs/Themes.md / public-docs/UserCustomization.md (theme + custom attribute structures used by these APIs) # The Storyteller List Views URL: /StorytellerListViews/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `storyteller-list-views` - Source: `public-docs/StorytellerListViews.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Showcase.md`, `Themes.md`, `StorytellerEmbeddedClipsView.md` ## Overview - React Native exports four list components (the intermediate native hierarchy is not exported): Stories Row/Grid and Clips Row/Grid. - Shared configuration covers categories or collections, display limits, `cellType`, theme overrides, string analytics `context`, and `uiStyle`; Clips lists also accept `adConfiguration`, rows add `visibleTiles`, and grids add `isScrollable`. - Each view exposes callbacks for data load lifecycle, tile taps, and player dismissal via `DataLoadCompletedEvent` and other typed payloads. - All list views expose `reloadData()` along with guidance on when to call it (mount, pull-to-refresh, data invalidation, configuration changes, network recovery). - Performance best practices cover `displayLimit` tuning, scrollable vs. non-scrollable grids, memory tips, and warnings against using FlatList on Android (use ScrollView or FlashList instead). ## When To Use - You need horizontally scrolling rows or grid layouts of Stories or Clips managed by Storyteller CMS. - You must embed multiple lists in custom layouts while retaining control over scrolling, theming, and analytics callbacks. ## Integration Steps 1. Await initialization, then pick the appropriate component (`StorytellerStoriesRowView`, `StorytellerStoriesGridView`, `StorytellerClipsRowView`, or `StorytellerClipsGridView`) based on content type and layout. 1. Supply a `configuration` object with categories/collections, display limits, optional theming/uiStyle, and row/grid-specific props (`visibleTiles`, `isScrollable`). 1. Provide handlers for `onDataLoadStarted`, `onDataLoadCompleted`, `onPlayerDismissed`, and `onTileTapped` to integrate loading states and analytics. 1. Keep a ref to call `reloadData()` at mount, on refresh actions, or after configuration changes; respect performance guidance (limit items, choose scroll strategy, avoid FlatList on Android). ## API Cheat Sheet - `StorytellerStoriesRowView` / `StorytellerStoriesGridView` — render stories; props include `configuration.categories`, `displayLimit`, `cellType`, `theme`, `uiStyle`, and row/grid-specific options. - `StorytellerClipsRowView` / `StorytellerClipsGridView` — render clips; `configuration.collection`, the same layout/theming knobs as stories, and optional Android-only `adConfiguration` (iOS Row/Grid ignore it). Android provider order uses `null` for native order, `[]` to disable standard between-Clips ads, or an ordered VAST/GAM/AdMob array. - Callbacks: `onDataLoadStarted()`, `onDataLoadCompleted(event)`, `onPlayerDismissed()`, `onTileTapped({ id })`. - `reloadData()` — available on every list view ref to refresh data manually. ## Examples - Code samples show mounted v11 rows/grids requesting data after host initialization and logging events, plus v10 class-based implementations. - Additional snippets demonstrate non-scrollable embedding inside a parent ScrollView and FlashList-based advanced layouts in the Showcase repo. ## Pitfalls / Notes - Set `displayLimit` appropriately; non-scrollable grids render all items up to this limit at once and can impact memory if left high. - Do not embed Storyteller views in React Native `FlatList` on Android; use `ScrollView` for small sets or `FlashList` for larger ones. - Give rows a height and scrollable grids a bounded height. Reload can fetch or refresh cached content; `displayLimit` limits rendered tiles rather than guaranteeing smaller network responses. ## Cross-References - public-docs/Showcase.md (real-world layout examples) - public-docs/Themes.md (cell theming + grid column configuration) - public-docs/StorytellerEmbeddedClipsView.md (paired experiences that open from lists) # Storyteller Home URL: /StorytellerHome/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `storyteller-home` - Source: `public-docs/StorytellerHome.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `StorytellerListViews.md`, `Themes.md` ## Overview - The exported `StorytellerHomeView` renders multiple Stories and Clips rows/grids inside a single list-driven screen. - Props: `configuration.homeId` (selects a CMS-defined home layout), optional `configuration.theme` (light/dark overrides) and `configuration.uiStyle` (`UIStyle.auto | light | dark`), and string analytics `configuration.context`. - Provides `style` for layout sizing plus a `StorytellerHomeViewInterface` ref exposing `reloadData()`. - Example showcases v11 hooks and v10 class integrations including safe area usage. - Reload section demonstrates how to trigger data refresh (PTR alternative) via the ref. ## When To Use - You need a vertically scrollable hub combining multiple Storyteller rows/grids managed in CMS. - You want to refresh the entire home feed on pull-to-refresh or manual triggers. ## Integration Steps 1. After initialization, import `StorytellerHomeView` and create a `useRef` (or class ref) to call `reloadData()`. 1. Pass `configuration={{ homeId: 'your-home-id', theme, uiStyle }}` and apply container styles matching your screen. 1. Handle refresh interactions by calling `ref.current?.reloadData()` instead of re-mounting the component. ## API Cheat Sheet - `StorytellerHomeView` props — `configuration` (`homeId?`, `theme?`, `uiStyle?`, `context?`) plus `style`. - `StorytellerHomeViewInterface.reloadData()` — reloads all rows/grids defined by the current home configuration. ## Examples - v11 hook example wraps the view in a standard `View`, passes `homeId`, and uses `ref.current?.reloadData()` for manual refreshes. - v10 example shows SafeAreaView usage plus the legacy `identifier` prop for earlier SDKs. ## Pitfalls / Notes - `configuration.homeId` must match a configuration created in the Storyteller CMS; the component will render empty if not provisioned. - Provide a non-empty `homeId` and bounded height; Android renders no Home when the ID is omitted. Home exposes no RN data-load-started or completed callbacks. Always guard `ref.current` before calling `reloadData()` to avoid null reference errors. - Theme overrides follow the same light/dark structure as `Theme` objects referenced in `Themes.md`. ## Cross-References - public-docs/StorytellerListViews.md (rows/grids that appear inside Home layouts) - public-docs/Themes.md (theme object structure referenced by `configuration.theme`) # Embedded Clips URL: /StorytellerEmbeddedClipsView/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `storyteller-embedded-clips-view` - Source: `public-docs/StorytellerEmbeddedClipsView.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `StorytellerListViews.md`, `Themes.md` ## Overview - To start silently, await initialization and `StorytellerSdk.mute()` before mounting the view. Runtime mute/unmute preserve playback; keep normal `willShow()`/`willHide()` lifecycle handling. - To show a prompt over continuing video, await mute and keep the embedded view mounted. Dismissing the prompt does not automatically unmute. - `StorytellerEmbeddedClipsView` embeds the clips player inline with configurable collection/category/clip defaults, per-view theme and analytics context, optional Clips ad configuration, and Android-only `topInsets`. - Event callbacks include `onDataLoadStarted`, `onDataLoadCompleted({ success, error, dataCount? })`, `onTopLevelBackTapped({ canGoBack })`, and `onCanGoBackChanged({ canGoBack })`; Embedded Clips currently omits `dataCount`. - Supports optional SDK-managed top-level back button via `topLevelBackButtonEnabled`. - Exposes imperative methods through `StorytellerEmbeddedClipsViewInterface`: `willShow`, `willHide`, `reloadData`, `goBack`, `getCanGoBack`. - Examples cover v11 (hooks) and v10 (class) implementations, including how to pause/resume playback during navigation transitions and how to trigger reloads. ## When To Use - You need a vertically scrollable clips experience embedded in your own screen instead of launching the full-screen player. - You must control playback when navigating tabs, drawers, or backgrounding the app. ## Integration Steps 1. After initialization, render `StorytellerEmbeddedClipsView` with a `useRef` (or class ref) and pass the desired `configuration` (collection/category/clip/openedReason/theme/context/adConfiguration/topInsets). 1. Wire `onDataLoadStarted`/`Completed` for loading states, and decide whether the SDK or your app handles the top-level back button via `topLevelBackButtonEnabled` plus `onTopLevelBackTapped`. 1. Use `useFocusEffect`, navigation listeners, or AppState handlers to call `willShow()`/`willHide()` so playback pauses when the view is hidden, and call `reloadData()` when the collection needs refreshing. 1. On Android and iOS 11.6.0+, call `getCanGoBack()` or read `onCanGoBackChanged` to decide whether the SDK can pop an internally pushed category screen. `goBack()` remains Android-only and is a no-op on iOS. ## API Cheat Sheet - `configuration` — `{ collection?, category?, clipId?, openedReason?, theme?, context?, adConfiguration?, topInsets? }` describing content, presentation, analytics context, optional pre-roll/bottom-banner opt-in, and Android standard between-Clips provider order. - `onDataLoadCompleted(event)` — receives `success`, `error`, and optional `dataCount`; list/Card components include the count, while Embedded Clips currently does not. - `topLevelBackButtonEnabled?: boolean` — show/hide SDK back button at the collection root. - `onTopLevelBackTapped(event)` — invoked when the SDK back button is pressed; `event.canGoBack` indicates whether the SDK will handle the action. - `StorytellerEmbeddedClipsViewInterface` — methods `willShow()`, `willHide()`, `reloadData()`, Android-only `goBack()`, and Android/iOS 11.6.0+ `getCanGoBack()`. ## Examples - v11 hook example demonstrates configuring collection/category defaults and logging data-load plus navigation callbacks. - Auto-pause sample uses `useFocusEffect` to wrap `willShow()`/`willHide()` around navigation focus changes; v10 example shows equivalent AppState handling. - Reload example shows a button calling `ref.current?.reloadData()`. ## Pitfalls / Notes - Always call `willHide()` before removing the view or switching tabs so videos pause and resources release. - Supply a non-empty collection for iOS and a bounded height. `openedReason` accepts a string; native parsers recognize `deeplink` and otherwise use an internal default. `topInsets` only applies on Android; ensure iOS layouts handle safe areas separately. - `betweenClipsAdProviderOrder` only applies on Android: omit/pass `null` for native order, use `[]` to disable standard between-Clips ads, or pass an ordered VAST/GAM/AdMob array. IMA opening pre-roll is separate. - Guard ref calls (`ref.current?.method()`) because the interface is only set after the component mounts. ## Cross-References - public-docs/StorytellerListViews.md (list components that navigate into Embedded Clips) - public-docs/Storyteller.md (initialization and shared analytics events) - public-docs/Themes.md (clip theming options referenced when embedding) # Card Component URL: /StorytellerCardView/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `storyteller-card-view` - Source: `public-docs/StorytellerCardView.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `StorytellerListViews.md` ## Overview - `StorytellerCardView` renders a single adaptive card for a given clips collection and auto-measures its height as content loads and changes. - Props include `configuration.collectionId` (required), string analytics `configuration.context`, `style`, and optional `onDataLoadCompleted` using `DataLoadCompletedEvent`. - Height updates include changes to the displayed card after an action reorders its collection. Changing `collectionId` starts a new card instance without reusing the previous collection’s measured height. - Exposes an imperative `reloadData()` method via `StorytellerCardViewInterface` refs. - Usage example shows managing a ref, handling success/error in `onDataLoadCompleted`, and refreshing when needed. ## When To Use - You want to embed a single Storyteller card (e.g., hero clip) instead of a full list or grid. - You need finer control over reload timing or analytics around a single collection. ## Integration Steps 1. After initialization, import `StorytellerCardView` and create a `useRef(null)` (or class ref) for imperative calls. 1. Render the component with `configuration={{ collectionId: 'your-collection-id' }}` and optional `style` sizing the card. 1. Listen to `onDataLoadCompleted` for success/error and call `ref.current?.reloadData()` when content should refresh. ## API Cheat Sheet - `StorytellerCardView` props — `configuration.collectionId` (string, required), optional `style`, `onDataLoadCompleted(event: DataLoadCompletedEvent)`. - `StorytellerCardViewInterface.reloadData()` — reloads the card’s data when called via a ref. ## Examples - Provided functional component example shows handling `DataLoadCompletedEvent`, logging successes, and invoking `reloadData()` from a button or effect. ## Pitfalls / Notes - The card starts at zero height and computes its height from native content measurements. Its configuration starts loading; it exposes completion but no data-load-started callback. - Call `reloadData()` only after the ref is set; guard with `if (ref.current) { ... }`. - Card fonts and font features come from the CMS. On Android, bundle those fonts in `android/app/src/main/res/font/` under the exact name the CMS returns; `assets/fonts` is not used for them. On iOS, the CMS font name must match a registered font. ## Cross-References - public-docs/StorytellerListViews.md (list components that share configuration patterns) - public-docs/Storyteller.md (initialization + shared event types) # Themes URL: /Themes/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `themes` - Source: `public-docs/Themes.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `StorytellerListViews.md`, `StorytellerHome.md` ## Overview - Set a global `Theme` with `StorytellerSdk.setTheme(theme)` or a view-specific theme with `configuration.theme`. - The exported `Theme` requires `light` and `dark`; nested fields are optional. `configuration.uiStyle` selects light, dark or device appearance. - Tables describe the RN integration source with Android 12.1.1/iOS 11.8.0 local defaults, cascades and confirmed platform limitations. Tenant settings can affect resolved appearance. - Groups cover colors, primitives, lists, tiles/live chips, Stories and Clips Player, Cards, buttons, instructions, engagement units, Search, fonts, Home, sheets, gradients and modal/Embedded layout. ## Integration Steps 1. Import `Theme` and the relevant enums; provide both mode objects. 1. Override only required fields and set the theme globally or in a view's configuration. 1. Package images and fonts in the host app, and validate both platforms and appearances. ## API Cheat Sheet - `ThemeGradient` requires `startColor`, `endColor`, `startPosition`, `endPosition`; `GradientPosition` is numeric (0–8). Optional valid ordered `stops` support more than two colors. - `TextCase` and `ElementAlignment` are exported string enums; use enum members in TypeScript. - `FontProvider` names six font weights and optional `light`. The iOS parser requires all six regular-through-black strings even when TypeScript permits a partial object. - Android `assets/fonts` inputs need the exact filename, including extension; the separate `res/font` family lookup normalizes names. - `PlayerLikeAnimationResource` supports a common `name`, per-platform resource names and optional iOS `bundlePath`; set it under `icons.like.animation`. - `player.clips.modal` (RN 12.1.1+; Android 12.1.1/iOS 11.8.0) customizes the full-screen Clips layout. Embedded Clips use `clips.spacing` and `embeddedVideoSizing`. ## Pitfalls / Notes - Per-view examples use `configuration={{ theme }}`; a top-level `theme` prop is not the wrapper contract. - Gradient positions omitted in untyped JavaScript fall back only on Android; iOS requires valid numeric positions and endpoints. - `home.headerTitle` is currently ignored on Android. `showMoreButton` and `icons.more` are not applied through the current RN/native theme path; iOS also ignores `icons.close`. - RN 12.0.2 and earlier do not include `player.clips.modal`. Android ignores ARGB string overrides for `player.liveChip.textColor`/`backgroundColor`, `rectangularTile.unreadIndicator.gradient` and the exported rectangular-chip alignment. Both platforms ignore `rectangularTile.unreadIndicator.alignment`. - Top-level `tiles.liveChip` is Android-only through the current RN parser; prefer nested circular/rectangular live chips for shared styling. - Native defaults include black `#1A1A1A`, zero grid top/bottom insets, read-ring width 1, poll border `colors.primary`, and poll answered-message `colors.white.primary`. - Modal sizes/insets use dp on Android and points on iOS. Invalid values keep defaults; navigation height is at least 48 and Android rounds fractional modal dimensions. ## Cross-References - public-docs/StorytellerListViews.md - public-docs/StorytellerHome.md # Ads URL: /Ads/ ## Task Help an engineer integrate Storyteller ads using the exported React Native contracts. Distinguish optional package setup from core initialization, and current APIs from the historical v10 example. ## Metadata - Slug: `ads` - Source: `public-docs/Ads.md` - Audience: React Native SDK integrators - Platforms: iOS and Android; IMA is Android phones only - Related: `Storyteller.md`, `StorytellerListViews.md`, `StorytellerEmbeddedClipsView.md` ## Overview - Core provides CMS-managed and client-supplied ads; GAM adds Google Ad Manager and AdMob; VAST adds generic and GAM VAST full-screen creatives; IMA adds one eligible opening Android Clips pre-roll. - Install optional packages at the core package version and rebuild. Register modules/listeners before ad-bearing content. Setup functions return void and do not initialize core. - GAM/AdMob need Google Mobile Ads host app IDs in Info.plist/AndroidManifest.xml and applicable iOS SKAdNetwork entries. Native dependency versions come from the integration package. - GAM and AdMob replace only the shared Google family; generic VAST and GAM VAST replace only the VAST family. Android IMA stays independent. Disable functions remove only their respective family. Google/VAST disabling completes pending JS requests with empty results but retains consumer-owned subscriptions; Google disabling retains the registered host enricher. - GAM full-screen requests use request IDs and dynamic ad-unit results. AdMob and Google bottom banners use static setup ad units. Native enrichment hooks keep Google/bidder objects outside JavaScript. - VAST dynamic parameters merge over static keys; GAM VAST uses static setup and generated tag fields. VAST diagnostics are independent of analytics and debug logging; fields and error names vary by platform. - IMA callbacks receive current item metadata and optional next-Clip categories, without nextClip.contentId. They resolve once per request, override supplied fields, retain omitted static fields and replace supplied targeting maps. Callback failure/timeout falls back to static values. An unresolved complete tag skips pre-roll; GAM mode can still issue an unusable request if required fields are missing. - Core custom-ad events have no requestId, adIndex or nextClip in their public contract. Reply APIs complete the current pending callback and require a single listener owner. ## When To Use - Integrate CMS ads, custom creatives, GAM/AdMob, generic/GAM VAST, or Android opening IMA pre-roll. - Select request-specific GAM ad units, provide VAST parameters, enrich Google requests in native code, or configure eligible Clips placements. ## Integration Steps 1. Confirm tenant/placement eligibility and ad source with Storyteller Delivery; obtain template IDs, ad units and host app IDs as needed. 2. Install the selected optional package at the core version, complete platform setup and rebuild; install pods for iOS packages. 3. Register native GAM enrichment before setupGAMModule, and establish request listeners before presenting ad-bearing content. Initialize core separately. 4. For GAM full-screen ads, respond to getAdUnitForRequest with the unchanged requestId. For AdMob and bottom banners, supply static ad units in setup. 5. For generic VAST dynamic parameters, enable usesRequestParametersCallback and respond with the matching requestId within one second; static parameters remain on timeout. 6. For IMA, guard Android-only calls, select GAM-built or complete-tag mode, and explicitly enable preRollEnabled in the presentation. 7. For custom ads, subscribe to getAdsForList and finish the current request with completeAdRequest(ad) or failAdRequest(string); implement creative fetching in the host app. 8. Set preRollEnabled and bottomBannerEnabled explicitly in any supplied adConfiguration object. Use Android provider order/cadence/fetch mode when needed, respecting platform support. ## API Cheat Sheet - setupGAMModule({ customNativeTemplateId?, bottomBannerAdUnit?, customKvps? }) — GAM templates, static bottom-banner unit and extra targeting. Targeting is gated by Storyteller ad tracking. - setupAdMobModule({ nativeAdUnit, bannerAdUnit?, bottomBannerAdUnit?, enableBannerAdPriority?, customKvps? }) — native-first by default; banner priority is false unless enabled. - disableGoogleAdsModule() — removes GAM/AdMob and leaves other supported modules, listener ownership and native enricher registration intact. - getAdUnitForRequest(listener) — EventSubscription with { requestId, adRequest }; setAdUnitResult({ requestId, adUnitId }) resolves it. Android waits one second; iOS waits five. An empty ad unit means no selected GAM unit. - GAM/VAST AdRequestPayload — stories { placement, categories, story, adIndex } or clips { collection, clip, nextClip?, adIndex }. ItemInfo categories are readonly; current item contentId is optional, populated by Android 11.6.3+ and iOS 11.7.0+ callbacks. Android nextClip contains categories only and is omitted for empty categories; iOS can supply nextClip.contentId. - Core getAdsForList — direct { stories?: { placement, categories, story }, clips?: { collection, clip } }; current item contentId/categories, no public nextClip/adIndex/requestId. - completeAdRequest(StorytellerAd) / failAdRequest(string) — void current-pending custom-ad replies, without request correlation. - Android StorytellerSdkGamModule.registerAdRequestEnricher — prepared builder with success/no-fill/failure completion. Host owns bidder timeout; no-fill/failure continues un-enriched, cancellation ignores late completion. clearAdRequestEnricher affects subsequent setup. - iOS StorytellerGamSdk.registerAdRequestEnricher — main-actor async prepared Request mutation; finish mutation before returning, clear before subsequent setup. - setupImaGamModule / setupImaAdTagModule — Android-only static or callback setup; description/content/tag URLs are HTTPS and limited to 8192 characters. Optional positive integer load timeouts use milliseconds; omission retains IMA defaults. disableImaModule removes its internally owned callback subscription and module. - setupVASTModule({ baseUrl, requestParameters?, urlFormat?, enableDebugLogging?, usesRequestParametersCallback? }) — pathSegment by default, debug/callback flags false by default. Raw values are encoded; callback keys override static keys, and supplied values override generated bid parameters. - setupGAMVASTModule({ adUnit, descriptionUrl, contentUrl?, customParams?, tagParameters?, enableDebugLogging? }) — generated Google tag with raw custom targeting; tagParameters override generated fields. No JS request-parameter callback in this mode. - disableVASTModule() — removes generic/GAM VAST and completes pending parameter requests with empty parameters; consumer subscriptions remain. - getVASTRequestParametersForRequest / setVASTRequestParametersResult — matching requestId and optional parameters within one second; omission/empty map uses static values. - onVASTDiagnostics(listener) — requestStarted, requestCompleted, requestFailed, parseFailed, wrapperResolved, mappingFailed, mediaSelectionFailed; optional fields must be handled defensively. - StorytellerClipsAdConfiguration — supplied objects default omitted boolean flags to false. iOS applies placement flags to openCollection/openCollectionWithCategory and Embedded Clips, while rows/grids ignore them. - betweenClipsAdProviderOrder — Android-only: null/omitted preserves module order; [] disables standard provider attempts; populated arrays restrict/order recognized VAST/GAM/AdMob providers. IMA/banners are independent; iOS ignores it. - frequency / initialIndex — Android-only eligible standard cadence overrides; positive frequency, nonnegative index, with 0 opening and positive indices counting content Clips. Invalid/null inherits remote cadence. - bottomBannerFetchMode — RN 12.1.1+; Android-only justInTime default or prefetch of one next Clip; prefetch may request an unseen banner, and needs placement/unit/remote eligibility. - StorytellerAd — id, advertiserName, adFormat and trackingPixels are required; image/video asset needed, video preferred; action optional. Android ignores advertiserDescription, advertiserLogoURL, responseIdentifier and format value but still requires adFormat. ## Examples - Current GAM hooks subscribe, return matching requestId and remove the subscription. The v10 tab retains its legacy NativeEventEmitter contract. - IMA illustrates GAM-built/complete tags, callback overrides and an Android-guarded collection open with explicit preRollEnabled. - VAST shows raw static query parameters, dynamic result correlation, GAM tag setup and redacted diagnostics logging. - Custom-ad listener is an excerpt requiring host loadAdForRequest. Cadence/provider/fetch examples declare typed configuration objects. ## Pitfalls / Notes - Setup order can affect module priority because selected modules append after retained modules. An Android explicit provider order excludes unrecognized custom providers and skips unavailable providers. - Reply promptly to GAM/VAST; timeout uses an empty unit/dynamic parameter set and a late response cannot alter the requested ad. AdMob does not use the GAM listener. - IMA static targeting maps are replaced, not key-merged, by callback maps. Invalid callback URLs are discarded to allow fallback. With callback-only setup, return required mode fields. Missing complete tags skip pre-roll; missing GAM fields can still create an unusable request. - Supply raw custom parameter values; let the SDK encode them. VAST final URL limit is 2048 characters on Android and 2048 UTF-8 bytes on iOS. Path-segment mode needs a base without query/fragment. - VAST does not add an IMA-style player and cannot serve Clips bottom banners. Google banner unit configuration alone does not enable the placement. - Android adConfiguration defaults in the native SDK do not override explicit RN false values for omitted flags in a supplied object. iOS ignores provider order, cadence and fetch mode. - Custom-ad duration uses seconds; use integers for Android. Omit video duration for media duration; positive supplied duration can control iOS Story playback. Omitted image duration defaults to five seconds. - Supply nonempty custom action text for cross-platform behavior: iOS suppresses the action if text is absent/blank. inApp navigation emits StorytellerSdk.userNavigatedToApp. - The portrait video encoding profile is guidance; the bridge does not transcode or validate it. Avoid logging tags, targeting values or full diagnostics payloads. # Deeplinking URL: /Deeplinking/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `deeplinking` - Source: `public-docs/Deeplinking.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `StorytellerListViews.md` ## Overview - Requires native platform setup plus the React Native `Linking` bridge; iOS supports universal links and recognized Storyteller schemes and must forward URLs through `RCTLinkingManager` in `AppDelegate`. - Introduces `userNavigatedToApp`, an SDK event that emits the configured URL for an in-app action; the URL scheme alone does not determine the action type. - `StorytellerSdk.isStorytellerDeeplink` (sync boolean in v11+, callback in v10) lets you filter URLs before calling `openDeeplink`. - `StorytellerSdk.openDeeplink` opens supported Story/Page, Clips/category and Sheet URLs. The `DeepLink` spelling is also exported. On Android its Promise confirms invocation, not eventual content visibility, and late errors are not emitted by `onPlayerOpenFailed` for this method. - Example implementations show how to combine `Linking.addEventListener('url', ...)`, `Linking.getInitialURL()`, and the SDK helpers for both hooks-based and class-based apps. ## When To Use - You need Storyteller content to open from push notifications, universal links, or other external entry points. - Your stories contain CTA buttons that should route users back into your app via custom schemes. ## Integration Steps 1. Complete platform-native deep link registration (Associated Domains on iOS, intent filters on Android) and ensure `AppDelegate.mm` forwards URLs to `RCTLinkingManager`. 1. Subscribe early and retain URLs until initialization and host readiness. In React Native, call `StorytellerSdk.isStorytellerDeeplink(url)` before invoking `StorytellerSdk.openDeeplink(url)`. 1. Listen to `StorytellerSdk.userNavigatedToApp` so CTA buttons configured in Storyteller CMS can hand off your custom URLs; route the user inside your app when this fires. 1. On startup, call `Linking.getInitialURL()` (or handle `AppState` in v10) to process links that launched the app. ## API Cheat Sheet - `StorytellerSdk.isStorytellerDeeplink(url)` — returns `boolean` in v11+, or accepts a callback in v10, letting you guard against non-Storyteller URLs. - `StorytellerSdk.openDeeplink(url)` — Promise-based (v11+) or callback (v10) method that navigates directly to the Story, Page, or Clip referenced by the deeplink. - `StorytellerSdk.userNavigatedToApp(listener)` — event emitter delivering `{ url }` when a Storyteller action is configured as in-app navigation; unsubscribe on cleanup. ## Examples - Hook-based sample shows how to register a `Linking` listener, gate URLs through `isStorytellerDeeplink`, open them, and remove the subscription on unmount. - Legacy class-based example demonstrates tying `Linking` and `AppState` to `StorytellerSdk.isStorytellerDeeplink` and `openDeeplink` when using refs. ## Pitfalls / Notes - Use Associated Domains for universal links and register any received custom scheme in `Info.plist`. The shown Objective-C++ forwarding methods need Swift equivalents in a Swift AppDelegate. - `userNavigatedToApp` is not the same as analytics events—it is the callback that delivers action URLs you must handle. - Always null-check the URL returned from `Linking.getInitialURL()` and guard with `isStorytellerDeeplink` before calling `openDeeplink`. ## Cross-References - public-docs/Storyteller.md (core SDK initialization and Linking helper context) - public-docs/StorytellerListViews.md (rows/grids that can emit action URLs routed back into your app) # Custom Attributes URL: /UserCustomization/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `user-customization` - Source: `public-docs/UserCustomization.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Storyteller.md`, `Analytics.md` ## Overview - `StorytellerSdk.setCustomAttribute(key, value)` stores string attributes used by SDK requests that carry user attributes. Use content-configuration keys; iOS lowercases keys while Android preserves case. - `StorytellerSdk.customAttributes()` returns all current attributes; `setCustomAttributes(attributes)` replaces the map and `removeCustomAttribute(key)` deletes a single entry. - Follow mutation APIs require the tenant to use app-managed following; `setFollowedCategories()` atomically replaces the full app-managed set, while the add/remove helpers make incremental changes and `getFollowableCategories()` fetches backend metadata plus current state. - `StorytellerSdk.categoryFollowActionTaken` fires whenever the user follows/unfollows inside Storyteller UI. On iOS 11.6.0+, its optional `category.description` is included when supplied by the backend. - Best practices call out timing (set after initialization before loading content), privacy/legal compliance, and avoiding excessive attributes. ## When To Use - You must send additional context (location, tier, experiment bucket) with Storyteller requests for personalization or reporting. - Your product exposes follow/favorite category concepts that should stay in sync with Storyteller’s followable categories UI. ## Integration Steps 1. After `StorytellerSdk.initialize`, call `StorytellerSdk.setCustomAttribute(key, String(value))` for each attribute you need; convert non-string types yourself. 1. Read, replace, or remove attributes via `await StorytellerSdk.customAttributes()`, `StorytellerSdk.setCustomAttributes(attributes)`, and `StorytellerSdk.removeCustomAttribute(key)` when a user updates preferences. 1. Await `StorytellerSdk.setFollowedCategories(categories)` when replacing the complete followed set before reloading content; use add/remove helpers for incremental changes, `getFollowableCategories()` for custom category management UIs, and `categoryFollowActionTaken` for in-SDK changes. ## API Cheat Sheet - `StorytellerSdk.setCustomAttribute(key: string, value: string)` — assigns/updates a string attribute. - `StorytellerSdk.setCustomAttributes(attributes: Record)` — replaces the custom attribute map. - `StorytellerSdk.customAttributes(): Promise>` — retrieves all attributes. - `StorytellerSdk.removeCustomAttribute(key)` — deletes one attribute. - `StorytellerSdk.addFollowedCategory(category)` / `addFollowedCategories(categories: string[])` — mark categories as followed locally. - `StorytellerSdk.setFollowedCategories(categories: string[]): Promise` — replace the resolvable app-managed set; an empty array clears it when enabled. SDK-managed following makes this a no-op; Android also requires personalization. - `StorytellerSdk.removeFollowedCategory(category)` — removes one followed category. - `StorytellerSdk.removeFollowedCategories(categories: string[])` — removes multiple followed categories. - `StorytellerSdk.isCategoryFollowed(category)` — checks whether one category is followed. - `StorytellerSdk.followedCategories(): Promise` — returns the current followed list. - `StorytellerSdk.getFollowableCategories(): Promise<{ categories }>` — returns backend category metadata and follow state. - `StorytellerFollowableCategories`, `StorytellerFollowableCategory`, `StorytellerFollowableCategoryPlacement` — exported result types; category string fields are optional across native platforms and `id` is required. - `StorytellerSdk.categoryFollowActionTaken(listener)` — event emitter delivering `{ category, isFollowing }`; iOS 11.6.0+ may populate optional `category.description`. ## Examples - Code snippets show setting attributes (stringifying numbers/booleans), fetching them via `await StorytellerSdk.customAttributes()`, and removing entries. - Followable category examples demonstrate adding/removing categories, fetching backend category metadata with follow state, and reacting to `categoryFollowActionTaken` events. ## Pitfalls / Notes - Values must be strings; convert numbers/booleans before calling `setCustomAttribute`. - Set attributes only after initialization and before loading content; updates made later only apply to future requests. - Use content category identifiers. Add/remove helpers return `void` while native work runs asynchronously; await `setFollowedCategories()` when the completed update must precede content refresh. ## Cross-References - public-docs/Storyteller.md (core SDK methods referenced here) - public-docs/Analytics.md (events that include custom attribute context) # Search URL: /Search/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `search` - Source: `public-docs/Search.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `Themes.md`, `Storyteller.md` ## Overview - Storyteller Search lets users query Stories, Clips and configured article sources with live suggestions and server-driven filters. - Requires enablement in the Storyteller dashboard; otherwise `isSearchEnabled()` returns `false` and `openSearch()` is a no-op. - Built-in filters include Date Posted (All, 24h, Week, Month, Year), Content Type (All, Stories, Clips, and configured Articles), and Sort By (Relevance, Like Count, Share Count, Date Posted). - On iOS `openSearch()` dismisses the current Storyteller player first; Android launches its Search activity. It returns `void` without a completion or load-error callback. - Theming hooks customize the back icon and heading on both platforms; iOS 11.6.0 and Android 11.6.3 also map complete Search input, suggestion, no-results, Filters sheet/option, and Apply-button styling. ## When To Use - You need a turnkey search UI for Storyteller content without building your own query interface. - Your app should expose search only when the tenant has the feature enabled. ## Integration Steps 1. Await initialization, then check `StorytellerSdk.isSearchEnabled()` before rendering or invoking a search entry point. 1. If enabled, call `StorytellerSdk.openSearch()` in response to your Search button; account for iOS dismissing an existing player first. 1. Optionally adjust Search-specific theming via `Theme.light.search` and `Theme.dark.search`; iOS 11.6.0 and Android 11.6.3 fields fall back independently when omitted or invalid. ## API Cheat Sheet - `StorytellerSdk.isSearchEnabled()` — boolean flag indicating whether Search is provisioned for the current API key. - `StorytellerSdk.openSearch()` — opens native Search when enabled; iOS dismisses the active player first, and Android launches Search. ## Examples - Sample snippet guards `openSearch()` with `isSearchEnabled()` and logs when Search is disabled. ## Pitfalls / Notes - Ensure the feature is enabled in the Storyteller dashboard; otherwise the APIs silently return. - Filter selections persist only during the active Search session; reopen resets them. ## Cross-References - public-docs/Themes.md (Search-specific theming options) - public-docs/Storyteller.md (core SDK initialization required before calling search APIs) # Using Storyteller React Native SDK Docs with AI Assistants URL: /AI/ ## Task You are helping an engineer integrate Storyteller. Use this documentation to answer questions, propose improvements, and point out missing details. Be precise and call out assumptions. ## Metadata - Slug: `ai` - Source: `public-docs/AI.md` - Audience: React Native SDK integrators - Platforms: `iOS`, `Android` - Related: `llms.txt` ## Overview - Explains how to load the Storyteller React Native SDK documentation into AI assistants so code suggestions stay aligned with the official API. - Describes benefits of grounding AI prompts (faster troubleshooting, accurate platform-specific answers, avoiding invented APIs). - Links a downloadable combined summary and complete per-page exports; include the exact installed RN version and platform in your prompt. - Provides vetted prompt examples for initialization, list components, deep links, and theming questions. ## When To Use - You are preparing context for an AI coding assistant working on Storyteller integrations. - You want prompt templates that keep assistants grounded in the official documentation. ## Integration Steps 1. Download `ai/llms.txt` from the docs site and add version/platform context. Use per-page exports for complete examples; Analytics/Changelog/Licenses are separate. 1. Add page-specific exports (for example `llms-storyteller-home.txt`) when troubleshooting a particular component or API. 1. Use the provided prompt patterns as a starting point, then verify the AI-generated code against the docs before shipping. ## API Cheat Sheet - `No runtime SDK APIs.` This page is workflow guidance for using Storyteller docs with AI tools. ## Examples - Prompt templates cover SDK initialization, `StorytellerStoriesRowView` integration, deep link handling via `StorytellerSdk.openDeeplink(...)`, and theming through `StorytellerSdk.setTheme(...)`. ## Pitfalls / Notes - Verify AI output against the docs for your release and the installed package declarations; upcoming native APIs may not be present in a published RN package. - Keep platform differences in mind when reviewing suggestions—iOS and Android requirements can diverge. ## Cross-References - public-docs/ai/llms.txt (aggregate bundle to load into AI tools) - public-docs/Storyteller.md (core SDK reference mentioned by prompts)