Configuring a StorytellerListView#
Note
Most of the example code snippets are using the StorytellerStoriesRowView type. The same configuration patterns apply to StorytellerStoriesGridView, StorytellerClipsRowView, and StorytellerClipsGridView, while StorytellerClipsPlayerView is called out separately where its single-clip source contract differs.
For more details on the specific features available for Rows and Grids, please see StorytellerRowView and StorytellerGridView
Initialization#
Stories initialization#
const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id'); // All categories
const storyRowWithCategories = new Storyteller.StorytellerStoriesRowView(
'stories-row-id',
['category-1', 'category-2']
);
Clips initialization#
const clipsRow = new Storyteller.StorytellerClipsRowView(
'clips-row-id',
'clip-collection-id'
);
Clips player initialization#
Use StorytellerClipsPlayerView when you want to mount the clips player inline instead of opening it from a row or grid. The legacy collection-based constructor still works, and the player can also mount from either a single clip ID or a single clip external ID.
const collectionPlayer = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
'clip-collection-id'
);
const singleClipPlayer = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ clipId: 'clip-id' }
);
const singleClipPlayerByExternalId = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ externalId: 'clip-external-id' }
);
The NextJS sample renders each configured list through StorytellerListView, which picks the correct row or grid component based on the layout metadata returned by the CMS.
Configuration#
The ListConfiguration class is used to configure the Storyteller.StorytellerStoriesRowView, Storyteller.StorytellerStoriesGridView, Storyteller.StorytellerClipsRowView, Storyteller.StorytellerClipsGridView, and Storyteller.StorytellerClipsPlayerView classes.
Stories configuration#
const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');
storyRow.configuration = {
basename: 'top-stories', // Needed if there are multiple lists on the same page
categories: ['category1', 'category2', 'category3'], // Stories only
cellType: Storyteller.CellType.round, // Only for `StorytellerStoriesRowView`
context: {
source: 'homepage-stories',
campaign: 'summer-league'
},
displayLimit: 10,
preload: true, // Stories only
theme: customTheme,
uiStyle: 'dark',
};
const storyRow = new Storyteller.StorytellerStoriesRowView('stories-row-id');
const storyRowConfiguration: IListConfiguration<'StorytellerStoriesRowView'> = {
basename: 'top-stories', // Needed if there are multiple lists on the same page
categories: ['category1', 'category2', 'category3'], // Stories only
cellType: Storyteller.CellType.round, // Only for `StorytellerStoriesRowView`
context: {
source: 'homepage-stories',
campaign: 'summer-league'
},
displayLimit: 10,
preload: true, // Stories only
theme: customTheme,
uiStyle: 'dark',
};
storyRow.configuration = storyRowConfiguration;
Clips configuration#
const clipsRow = new Storyteller.StorytellerClipsRowView(
'clips-row-id',
'collection-id'
);
clipsRow.configuration = {
basename: 'top-clips', // Needed if there are multiple lists with the same collection on the same page
context: {
source: 'homepage-clips',
campaign: 'summer-league'
},
displayLimit: 10,
theme: customTheme,
uiStyle: 'dark',
};
const clipsRow = new Storyteller.StorytellerClipsRowView(
'clips-row-id',
'collection-id'
);
const clipsRowConfiguration: IListConfiguration<'StorytellerClipsRowView'> = {
basename: 'top-clips', // Needed if there are multiple lists with the same collection on the same page
context: {
source: 'homepage-clips',
campaign: 'summer-league'
},
displayLimit: 10,
theme: customTheme,
uiStyle: 'dark',
};
clipsRow.configuration = clipsRowConfiguration;
Clips player configuration#
const clipPlayer = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ externalId: 'clip-external-id' }
);
clipPlayer.configuration = {
basename: 'nba-highlight-player',
context: {
source: 'homepage-highlight',
campaign: 'google-highlights'
},
theme: customTheme,
uiStyle: 'dark',
};
clipPlayer.topLevelBackButtonEnabled = true;
clipPlayer.delegate = {
onTopLevelBackTapped: () => {
window.history.back();
},
};
const clipPlayer = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ externalId: 'clip-external-id' }
);
const clipPlayerConfiguration: IStorytellerClipsPlayerConfiguration = {
externalId: 'clip-external-id',
basename: 'nba-highlight-player',
context: {
source: 'homepage-highlight',
campaign: 'google-highlights'
},
theme: customTheme,
uiStyle: 'dark',
};
clipPlayer.configuration = clipPlayerConfiguration;
clipPlayer.topLevelBackButtonEnabled = true;
clipPlayer.delegate = {
onTopLevelBackTapped: () => {
window.history.back();
},
};
Learn more
See the documentation for StorytellerStoriesRowView and StorytellerClipsRowView and StorytellerStoriesGridView and StorytellerClipsGridView for attributes specific to those components.
basename#
Each Stories/Clips view is assigned a basename which corresponds to the first segment of the hash URL fragment. For example:
https://www.getstoryteller.com/#basename/[STORY_ID]
https://www.getstoryteller.com/#basename/[COLLECTION_ID]/[CLIP_ID]
By default, the basename value is stories (for Stories) or clips (for Clips). You can override this using ListConfiguration:
storyRow.configuration = {
basename: 'top-stories',
};
If there is only one Stories/Clips view on a single page, setting the basename is optional. In this case, opening a Story will take the user to #stories/[STORY_ID], and #clips/[COLLECTION_ID]/[CLIP_ID] for Clips.
However, if there are multiple views on the same page, each Stories/Clips view's basename will be derived from its categories/collection. If multiple views have the same categories/collection, then you'll need to override their basename, so that each view has a unique basename. If all views have different categories, there's no need to override the basename, but you might choose to do so for improved readability of the player URL.
Note
Basenames are sanitized to include only ASCII letters, numbers, dashes (-), and underscores (_).
categories (Stories only)#
You can optionally set a list of category IDs for each list view. This means only stories published in these categories will be displayed in this list. If no categories are supplied, stories published in the 'Home' list will be shown.
You can use the configuration object to dynamically update the categories of a Storyteller row:
storyRow.configuration = {
categories: ['new-category-id-1', 'new-category-id-2'],
};
The category IDs can be copied from the Storyteller CMS.
Learn more
See Categories for more information about managing categories in the CMS.
collection (Clips only)#
When initializing a Clips view, a collection ID is required:
const clipsRow = new Storyteller.StorytellerClipsRowView(
'clips-row-id',
'clip-collection-id'
);
Once a Clips view has been initialized, you can update its collection by using the configuration object:
clipsRow.configuration = {
collection: 'new-clip-collection-id',
};
The collection ID can be copied from the Storyteller CMS.
Learn more
See Creating Collections for more information about managing collections in the CMS.
clipId / externalId (Clips player only)#
When initializing StorytellerClipsPlayerView for true single-clip playback, pass an object with either clipId or externalId:
const clipPlayerById = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ clipId: 'clip-id' }
);
const clipPlayerByExternalId = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ externalId: 'clip-external-id' }
);
You can also switch the mounted player to a different clip later by reassigning the configuration object with the identifier you want to use:
clipPlayerById.configuration = {
clipId: 'new-clip-id',
};
clipPlayerByExternalId.configuration = {
externalId: 'new-clip-external-id',
};
Only one primary source should be set at a time for StorytellerClipsPlayerView, so choose exactly one of collection, clipId, or externalId for a given player instance.
These same source fields are also supported when assigning
IStorytellerClipsPlayerConfiguration through clipPlayer.configuration.
topLevelBackButtonEnabled (Clips player only)#
Set topLevelBackButtonEnabled directly on a StorytellerClipsPlayerView instance to show the embedded top-level back button:
const clipPlayer = new Storyteller.StorytellerClipsPlayerView(
'clips-player-id',
{ externalId: 'clip-external-id' }
);
clipPlayer.topLevelBackButtonEnabled = true;
clipPlayer.delegate = {
onTopLevelBackTapped: () => {
window.history.back();
},
};
When the back button is tapped:
- If
clipPlayer.delegate.onTopLevelBackTappedis defined, the SDK calls that callback and leaves the next step to the host app. - If no callback is defined, the SDK falls back to
window.history.back().
topLevelBackButtonEnabled is a direct StorytellerClipsPlayerView property. It is not part of the configuration object.
When it is false or omitted, the embedded top-level back button is hidden and
onTopLevelBackTapped is not called from that button.
context#
Use the context property for optional context data that will be included in onUserActivityOccurred callbacks. This allows you to track which sources drive engagement with your content. When configured, context will be included in all analytics events for interactions with the list content.
displayLimit#
The displayLimit is the maximum amount of tiles that can be shown in the list (optional).
preload#
Set preload to true to start loading the player before the user opens a Story. This will improve the user experience but will impact performance scores as the page will load additional scripts before they're needed.
theme#
The theme property can be used to set the Theme for a Storyteller List. Setting the theme for a list will override the values set in Storyteller.sharedInstance.theme.list, only for this list.
const customTheme = new Storyteller.UiTheme({
light: {
lists: {
row: {
startInset: 0,
endInset: 0,
},
},
},
});
uiStyle#
The uiStyle adjusts whether Storyteller renders in light mode, dark mode, or follows the system setting.
uiStyle takes the following values:
auto- default value, the List View will adjust its color scheme automatically according to the current system UI modelight- force the List View to use the light themedark- force the List View to use the dark theme
The uiStyle can also be set on the container div using the data-ui-style attribute:
<div id="storyteller-row" data-ui-style="dark"></div>
Methods#
reloadData#
reloadData();
The reloadData method starts loading fresh data for all Stories (or Clips) from the API. On completion, it updates the Story/Clip data, starts pre-fetching content and updates the read status of the Stories/Clips. The onDataLoadStarted and onDataLoadComplete delegate methods are called accordingly (the latter with appropriate data depending on the result of the API requests).
const storyRow = new Storyteller.StorytellerStoriesRowView('row-id');
storyRow.reloadData();
openStory, openStoryByExternalId, openPage, openCollection, openClipByExternalId#
The openStory, openStoryByExternalId, openPage, openCollection, and openClipByExternalId methods have been moved to the main Storyteller instance.
Learn more
See Additional Methods for more information.