Configuring Storyteller#
Prerequisites#
Important: The initialize() method must be called before using any other Storyteller SDK methods or components. Call this method as early as possible in your app lifecycle (typically in your root component or App.tsx).
Core SDK Methods#
Initialization#
initialize(apiKey: string, externalId?: string): Promise<void>#
Initializes the Storyteller SDK with your API key and optional user identifier.
Parameters:
apiKey- API key provided by the Storyteller teamexternalId- (Optional) External ID of the user for personalization and analytics
Example:
try {
await StorytellerSdk.initialize('YOUR_API_KEY', 'user-123');
console.log('SDK ready');
} catch (error) {
console.error('Initialization failed:', error);
}
Status & Information#
isInitialized(): boolean#
Checks if Storyteller has been successfully initialized.
isPresentingContent(): boolean#
Returns whether any Storyteller content (stories, pages, clips, sheets) is currently being presented. Useful to avoid opening new content while something else is on screen.
Example:
if (!StorytellerSdk.isPresentingContent()) {
await StorytellerSdk.openStory('story-id-123');
}
currentApiKey(): string#
Returns the current API key.
version(): string#
Returns the current SDK version.
Theming#
setTheme(theme: Theme): void#
Customizes the appearance of the SDK. Pass a Theme object of shape { light: Partial<ThemeType>, dark: Partial<ThemeType> }. Each mode accepts partial overrides. This sets the default fallback theming style used to render Story items in lists and activities launched from a list. For more information, see Themes.
Localization#
setLocale(locale?: string | null): void#
Sets the SDK locale for localized content. Provide an ISO language code such as "en" or "fr". Pass null or omit the argument to clear the locale preference.
Example:
StorytellerSdk.setLocale('en-US');
StorytellerSdk.setLocale(null); // clear locale preference
Deep Links#
Deep links allow you to open specific Storyteller content programmatically. These methods open Stories or Clip Collections independently from list components rendered in your app. For more information, see Deep Links.
isStorytellerDeepLink(url: string): boolean#
Returns whether a URL is a Storyteller deep link. The legacy RN spelling isStorytellerDeeplink(url) is also available for backwards compatibility.
openDeepLink(url: string): Promise<void>#
Opens a Storyteller deep link. The legacy RN spelling openDeeplink(url) is also available for backwards compatibility.
openStory(id: string): Promise<void>#
Opens a Story by its Storyteller ID (internal ID from Storyteller CMS).
Parameters:
id- Story ID from Storyteller
Example:
try {
await StorytellerSdk.openStory('story-id-123');
} catch (error) {
console.error('Failed to open story:', error);
}
openStoryByExternalId(externalId: string): Promise<void>#
Opens a Story by its external ID (custom ID set by your organization). Use this when you want to reference stories using your own ID system.
Parameters:
externalId- Your custom external ID for the story
Example:
try {
await StorytellerSdk.openStoryByExternalId('my-story-123');
} catch (error) {
console.error('Failed to open story by external ID:', error);
}
openPage(id: string): Promise<void>#
Opens a Story Page (multi-story experience) by its ID.
Parameters:
id- Page ID from Storyteller
openCategory(category: string): Promise<void>#
Opens all Stories in a specific category.
Parameters:
category- Category name/tag
openCollection(id: string, clipId?: string, openReason?: StorytellerOpenReason, adConfiguration?: StorytellerClipsAdConfiguration): Promise<void>#
Opens a Clip Collection, optionally starting from a specific clip.
Parameters:
id- Collection IDclipId- (Optional) Specific clip ID to start fromopenReason- (Optional) Reason used for analyticsadConfiguration- (Optional) Per-presentation Clips ad placement controls
Example:
// Open collection from the beginning
await StorytellerSdk.openCollection('collection-123');
// Open collection starting from a specific clip
await StorytellerSdk.openCollection('collection-123', 'clip-456');
// Opt this presentation into Clips pre-roll and bottom banner placements
await StorytellerSdk.openCollection('collection-123', undefined, undefined, {
preRollEnabled: true,
bottomBannerEnabled: true,
});
StorytellerClipsAdConfiguration has two optional booleans:
preRollEnabled- Allows an opening Clips pre-roll request when Clips ads are available for the tenantbottomBannerEnabled- Allows a bottom banner ad when Clips bottom banner ads are available for the tenant
When adConfiguration is omitted, the native SDK platform default is preserved. When the object is supplied, omitted flags are treated as false.
preloadClips(collectionId: string, clipIds?: string[], preloadVideos?: boolean): Promise<string | null>#
Starts Android Clips preloading for a collection. Pass an empty or omitted clipIds array to let the native SDK choose clips, and set preloadVideos to true to include video assets. The promise resolves with a handle that can be passed to cancelPreloadClips(handle).
const preloadHandle = await StorytellerSdk.preloadClips(
'collection-123',
['clip-1', 'clip-2'],
true
);
if (preloadHandle) {
StorytellerSdk.cancelPreloadClips(preloadHandle);
}
The linked iOS SDK does not expose Clips preloading, so this method resolves null on iOS and cancelPreloadClips() is a no-op.
openClipByExternalId(collectionId: string, externalId: string): Promise<void>#
Opens a specific clip within a collection using external IDs.
Parameters:
collectionId- Collection IDexternalId- Clip external ID
openCollectionByExternalId(collectionId, externalId) is also available as an alias for the Android native API naming.
openSearch(): void#
Opens the Storyteller search interface, allowing users to search through available content.
isSearchEnabled(): boolean#
Checks if search is available for the current API key and configuration. Use this to conditionally show a Search button.
Example:
if (StorytellerSdk.isSearchEnabled()) {
StorytellerSdk.openSearch();
}
openSheet(id: string): Promise<void>#
Opens a Sheet by its ID. Sheets are bottom or full-screen surfaces used to show additional content and actions.
Parameters:
id- Sheet ID from Storyteller
Example:
try {
await StorytellerSdk.openSheet('sheet-id-123');
} catch (e) {
console.warn('Failed to open sheet', e);
}
openCollectionWithCategory(id: string, category?: string, openReason?: StorytellerOpenReason, adConfiguration?: StorytellerClipsAdConfiguration): Promise<void>#
Opens a Clip Collection with an optional category context.
Parameters:
id- Collection IDcategory- (Optional) Category identifier to scope the collectionopenReason- (Optional) Reason used for analyticsadConfiguration- (Optional) Per-presentation Clips ad placement controls
Example:
await StorytellerSdk.openCollectionWithCategory('collection-123', 'sports');
await StorytellerSdk.openCollectionWithCategory('collection-123', 'sports', undefined, {
bottomBannerEnabled: true,
});
Content Counts#
Methods to query counts for UI badges, tabs, or prefetch logic.
getStoriesCount(categoryIds: string[]): Promise<number>#
Returns the number of available stories for the specified categories.
Parameters:
categoryIds- Array of category identifiers
Example:
const count = await StorytellerSdk.getStoriesCount(['news', 'sports']);
setStoriesBadge(count);
getClipsCount(collectionId: string): Promise<number>#
Returns the number of clips available in the specified collection.
Parameters:
collectionId- Collection identifier
Example:
const clips = await StorytellerSdk.getClipsCount('collection-123');
console.log('Clips available:', clips);
getClipsCountForCategories(categoryIds: string[]): Promise<number>#
Returns the number of clips available for the specified categories on Android. On iOS, use getClipsCount(collectionId).
const clips = await StorytellerSdk.getClipsCountForCategories(['news', 'sports']);
console.log('Clips available:', clips);
Player Control#
isPlayerVisible(): boolean#
Returns whether the native player is visible. This is an alias for isPresentingContent() in React Native.
isPlayerMuted(): Promise<boolean>#
Returns whether the player is currently muted on iOS. Android does not expose a matching native API in the linked SDK version and rejects this method.
dismissPlayer(animated: boolean, reason: string): void#
Programmatically closes the currently open Story player.
Parameters:
animated- Whether to animate the dismissalreason- Reason for dismissal (for analytics)
Example:
StorytellerSdk.dismissPlayer(true, 'user_action');
resumePlayer(): void#
Resumes playback after the player has been paused due to overlays, app lifecycle changes, or custom logic.
Example:
// When your overlay/modal closes or app regains focus
StorytellerSdk.resumePlayer();
setUseCustomShareHandling(useCustomShareHandling: boolean): void#
Controls whether Storyteller opens the platform share sheet itself or emits shareButtonTapped so your app can present a custom share flow. When custom handling is enabled, call resumePlayer() after your share UI is dismissed.
Example:
StorytellerSdk.setUseCustomShareHandling(true);
const subscription = StorytellerSdk.shareButtonTapped(({ text, title, url }) => {
// Present your own share UI with the payload, then resume Storyteller playback.
StorytellerSdk.resumePlayer();
});
Custom Attributes#
Custom attributes allow you to associate metadata with users for personalization and targeting. For more information, see User Customization.
setCustomAttribute(key: string, value: string): void#
Sets or updates a single user attribute.
setCustomAttributes(attributes: Record<string, string>): void#
Replaces the current custom attributes with the supplied string key/value map.
removeCustomAttribute(key: string): void#
Removes a single user attribute.
customAttributes(): Promise<Record<string, string>>#
Returns the current custom attributes.
Followable Categories#
Followable categories allow you to associate metadata with users for personalization and targeting. For more information, see User Customization.
addFollowedCategory(category: string): void#
Marks one category as followed.
addFollowedCategories(categories: string[]): void#
Marks multiple categories as followed.
removeFollowedCategory(category: string): void#
Removes one followed category.
removeFollowedCategories(categories: string[]): void#
Removes multiple followed categories.
isCategoryFollowed(category: string): boolean#
Returns whether a category is currently followed.
followedCategories(): Promise<string[]>#
Returns the current followed category identifiers.
getFollowableCategories(): Promise<StorytellerFollowableCategories>#
Fetches the backend-backed category catalog for the current user, including category metadata and isFollowed state for custom category management UIs.
Ads Integration#
For more information on integrating ads, see Ads.
Event Handling#
The Storyteller SDK emits events for user interactions, navigation, and ad requests. With React Native's New Architecture, these events are exposed as callable EventEmitter functions on the StorytellerSdk object.
Important: Always remove event listeners when components unmount to prevent memory leaks.
Available Events#
The SDK provides five event emitters:
onUserActivityOccurred- Fires for all user engagement events (views, taps, swipes, completions, etc.)userNavigatedToApp- Fires when user taps an action button that navigates to your appshareButtonTapped- Fires when custom share handling is enabled and the user taps a Story or Clip share buttoncategoryFollowActionTaken- Fires when user follows or unfollows a categorygetAdsForList- Fires when SDK requests ads for stories or clips
Event Subscription Pattern#
Each event emitter is a function that accepts a callback and returns a subscription object with a remove() method:
const subscription = StorytellerSdk.eventName((event) => {
// Handle event
});
// Clean up when done
subscription.remove();
Event Examples#
1. User Activity Tracking#
Track all user interactions within the Storyteller experience:
import { useEffect } from 'react';
import StorytellerSdk from '@getstoryteller/react-native-storyteller-sdk';
function MyComponent() {
useEffect(() => {
const subscription = StorytellerSdk.onUserActivityOccurred((event) => {
console.log('Event type:', event.type);
console.log('Event data:', event.data);
// Send to your analytics service
analytics.track(event.type, event.data);
});
return () => {
subscription.remove(); // Cleanup
};
}, []);
return (/* ... */);
}
2. App Navigation Events#
Handle when users tap action buttons that navigate to your app:
import { useEffect } from 'react';
import { Alert } from 'react-native';
import StorytellerSdk from '@getstoryteller/react-native-storyteller-sdk';
function MyComponent() {
useEffect(() => {
const subscription = StorytellerSdk.userNavigatedToApp((event) => {
console.log('Navigation URL:', event.url);
// Parse the URL and navigate within your app
});
return () => {
subscription.remove();
};
}, []);
return (/* ... */);
}
3. Category Follow/Unfollow Events#
Track when users follow or unfollow categories:
import { useEffect } from 'react';
import StorytellerSdk from '@getstoryteller/react-native-storyteller-sdk';
function MyComponent() {
useEffect(() => {
const subscription = StorytellerSdk.categoryFollowActionTaken((event) => {
console.log('Category:', event.category.name);
console.log('Is Following:', event.isFollowing);
// handle the follow/unfollow action
});
return () => {
subscription.remove();
};
}, []);
return (/* ... */);
}
4. Ad Request Events#
Handle ad requests for client-side ad integration
For complete ad integration details, see Ads.
Privacy & Analytics#
Event Tracking Options#
The eventTrackingOptions property customizes Storyteller's analytics and tracking behavior. This is an object of type StorytellerEventTrackingOptions which allows certain features to be disabled based on user privacy choices and regulatory requirements.
Note: By default, all tracking options are enabled.
Methods#
eventTrackingOptions(): Promise<StorytellerEventTrackingOptions>#
Retrieves the current tracking options configuration.
Example:
const options = await StorytellerSdk.eventTrackingOptions();
console.log('Tracking enabled:', options.enableStorytellerTracking);
To change tracking options, pass the new configuration into initialize(...) again. The linked native SDKs expose eventTrackingOptions as read-only after initialization.
API Reference#
Type Definitions#
Recommended imports to use SDK types directly and avoid drift:
import type {
Theme,
StorytellerEventTrackingOptions,
StorytellerClipsAdConfiguration,
StorytellerFollowableCategories,
StorytellerFollowableCategory,
StorytellerFollowableCategoryPlacement,
StorytellerAd,
StorytellerAdActionType,
DataLoadCompletedEvent,
ShareButtonTappedEvent,
Category,
ItemInfo,
StoriesGridDimensionsState,
} from '@getstoryteller/react-native-storyteller-sdk';
import { EventType } from '@getstoryteller/react-native-storyteller-sdk';
interface StorytellerEventTrackingOptions {
enablePersonalization?: boolean;
enableStorytellerTracking?: boolean;
enableUserActivityTracking?: boolean;
enableAdTracking?: boolean;
enableFullVideoAnalytics?: boolean;
enableRemoteViewingStore?: boolean;
disabledFeatures?: string[]; // e.g., ['all', 'clipLikes', 'pollVotes']
}
interface CustomAttributesResult {
[key: string]: string;
}
interface StorytellerFollowableCategories {
categories: StorytellerFollowableCategory[];
}
interface StorytellerFollowableCategory {
id: string;
name?: string;
displayTitle?: string;
externalId?: string;
type?: string;
placement?: StorytellerFollowableCategoryPlacement;
thumbnailUrl?: string;
isFollowed: boolean;
}
interface StorytellerFollowableCategoryPlacement {
title: string;
code: string;
}
interface StorytellerClipsAdConfiguration {
preRollEnabled?: boolean;
bottomBannerEnabled?: boolean;
}
interface ShareButtonTappedEvent {
text: string;
title: string;
url: string;
}
// Selected exported types (see package exports for the complete definitions)
interface Category {
name: string;
externalId: string;
displayTitle: string;
type: string;
placement: string;
}
interface ItemInfo {
categories: Category[];
}
interface AdRequestInfo {
stories?: {
placement: string;
categories: string[];
story: ItemInfo;
};
clips?: {
collection: string;
clip: ItemInfo;
};
}
// EventType is an enum exported from the SDK (e.g., 'openedStory', 'dismissedStory', ...)
// UserActivityData is a structured object; see Analytics.md for field documentation
Summary of All Methods#
| Method | Return Type | Description |
|---|---|---|
initialize(apiKey, externalId?) |
Promise<void> |
Initialize SDK |
isInitialized() |
boolean |
Check if initialized |
isPresentingContent() |
boolean |
Check if any content is presenting |
currentApiKey() |
string |
Get current API key |
version() |
string |
Get SDK version |
setTheme(theme: Theme) |
void |
Apply custom theme |
setLocale(locale?: string \| null) |
void |
Set or clear SDK locale |
isStorytellerDeepLink(url) |
boolean |
Validate deep link URL |
isStorytellerDeeplink(url) |
boolean |
Backwards-compatible deep link validator alias |
openDeepLink(url) |
Promise<void> |
Open deep link |
openDeeplink(url) |
Promise<void> |
Backwards-compatible deep link opener alias |
openStory(id) |
Promise<void> |
Open story by ID |
openStoryByExternalId(externalId) |
Promise<void> |
Open story by external ID |
openPage(id) |
Promise<void> |
Open story page |
openSheet(id) |
Promise<void> |
Open sheet by ID |
openCategory(category) |
Promise<void> |
Open category |
openCollection(id, clipId?, openReason?, adConfiguration?) |
Promise<void> |
Open collection |
openCollectionWithCategory(id, category?, openReason?, adConfiguration?) |
Promise<void> |
Open collection for a category |
openClipByExternalId(collectionId, externalId) |
Promise<void> |
Open clip by external ID |
openCollectionByExternalId(collectionId, externalId) |
Promise<void> |
Alias for Android native collection external ID naming |
openSearch() |
void |
Open search interface |
isSearchEnabled() |
boolean |
Check if search is enabled |
isPlayerVisible() |
boolean |
Alias for isPresentingContent() |
isPlayerMuted() |
Promise<boolean> |
Check iOS player mute state |
dismissPlayer(animated, reason) |
void |
Close player |
resumePlayer() |
void |
Resume a paused player |
setUseCustomShareHandling(enabled) |
void |
Enable or disable app-managed share handling |
setCustomAttribute(key, value) |
void |
Set user attribute |
setCustomAttributes(attributes) |
void |
Replace all custom attributes |
removeCustomAttribute(key) |
void |
Remove user attribute |
customAttributes() |
Promise<CustomAttributesResult> |
Get all attributes |
addFollowedCategory(category) |
void |
Follow category |
addFollowedCategories(categories) |
void |
Follow multiple categories |
removeFollowedCategory(category) |
void |
Unfollow category |
removeFollowedCategories(categories) |
void |
Unfollow multiple categories |
isCategoryFollowed(category) |
boolean |
Check whether a category is followed |
followedCategories() |
Promise<string[]> |
Get followed categories |
getFollowableCategories() |
Promise<StorytellerFollowableCategories> |
Get followable category metadata and follow state |
getStoriesCount(categoryIds) |
Promise<number> |
Get count of stories for categories |
getClipsCount(collectionId) |
Promise<number> |
Get count of clips in a collection |
getClipsCountForCategories(categoryIds) |
Promise<number> |
Get count of clips for Android categories |
preloadClips(collectionId, clipIds?, preloadVideos?) |
Promise<string \| null> |
Start Android Clips preloading and return a cancel handle; resolves null on iOS |
cancelPreloadClips(handle) |
void |
Cancel Android Clips preloading; no-op on iOS |
completeAdRequest(ad) |
void |
Complete a client-supplied ad request |
failAdRequest(error) |
void |
Fail a client-supplied ad request |
eventTrackingOptions() |
Promise<StorytellerEventTrackingOptions> |
Get tracking options |
Legacy Storyteller Methods (<v10.x)#
interface StorytellerSdkInterface
extends NativeModulesStatic,
NativeModule,
EventSubscriptionVendor {
isInitialized(callback: ({result}: {result: boolean}) => void): void;
isStorytellerDeeplink(url: string, callback: (result: {result: boolean}) => void): void;
currentUserId(callback: ({result}: {result: string}) => void): void;
currentApiKey(callback: ({result}: {result: string}) => void): void;
version(callback: ({result}: {result: string}) => void): void;
setTheme(theme: Partial<Theme>): void;
openDeeplink(url: string, callback: (result: boolean) => void): void;
openStory(id: string, errorCallback: (error: string) => void): void;
openPage(id: string, errorCallback: (error: string) => void): void;
openCategory(category: string, errorCallback: (error: string) => void): void;
openStoryByExternalId(
id: string,
errorCallback: (error: string) => void
): void;
openClipByExternalId(
collectionId: string,
externalId: string,
errorCallback: (error: string) => void
): void;
openCollection(
id: string,
clipId?: string,
errorCallback?: (error: string) => void
): void;
openSearch(): void;
eventTrackingOptions(callback: (options: StorytellerEventTrackingOptions) => void): void;
setEventTrackingOptions(options: StorytellerEventTrackingOptions): void;
dismissPlayer(animated: boolean, reason: string): void;
setCustomAttribute(key: string, value: string): void;
removeCustomAttribute(key: string): void;
customAttributes(
callback: (result: { [key: string]: string | number | boolean }) => void
): void;
setLocale(locale?: string): void;
addFollowedCategory(category: string): void;
addFollowedCategories(categories: string[]): void;
removeFollowedCategory(category: string): void;
followedCategories(callback: (categories: string[]) => void): void;
initialize(
data: {
apiKey: string;
externalId?: string | null;
},
callback: (callback: { result: boolean; message: string }) => void
): void;
};
Event Handlers#
| Event Handler | Callback Parameter | Description |
|---|---|---|
onUserActivityOccurred(callback) |
(event: { type: EventType, data: UserActivityData }) => void |
Subscribe to user activity events |
userNavigatedToApp(callback) |
(event: { url: string }) => void |
Subscribe to app navigation events |
shareButtonTapped(callback) |
(event: { text: string, title: string, url: string }) => void |
Subscribe to custom share payloads |
categoryFollowActionTaken(callback) |
(event: { category: Category, isFollowing: boolean }) => void |
Subscribe to category follow/unfollow events |
getAdsForList(callback) |
(adRequest: AdRequestInfo) => void |
Subscribe to ad request events |
All event handlers return a subscription object with a remove() method for cleanup.
Related Documentation#
- StorytellerListViews - Stories and clips list/grid component documentation
- StorytellerEmbeddedClipsView - Embedded clips player component guide
- StorytellerHome - Home view component documentation
- Themes - Customizing SDK appearance
- Ads - Integrating advertisements
- User Customization - User metadata and targeting
- Users - User management and authentication
- Deeplinking - Deep linking and navigation handling
- Search - Content search functionality
- Analytics - User activity tracking and analytics integration