This quickstart shows one row of published Stories on a web page. You add a
container, initialize the SDK, create the row, and check that Stories loaded.
Before you start lists what you need.
The steps below use the SDK as Storyteller. The samples use await, which
works only in JavaScript modules and inside async functions. In a classic
<script>, wrap the code in an async function, as shown in
Handle initialization errors.
The row sizes its tiles to the container's height, so set a height on the
container. If the container has no height, the SDK uses a default tile height
(160 px for square tiles, 120 px or 140 px for round tiles). When logging is
enabled, it also logs a warning.
Warning
The container ID must be unique on the page and
follow best practices for HTML IDs.
Use only ASCII letters, numbers, dashes (-), and underscores (_).
Replace demo-api-key with your API key. If the user is signed in, pass your
user ID as externalId. With the default privacy options, the user's viewing
history then follows them across browsers and devices:
The constructor takes the container ID and an optional list of Category IDs:
StorytellerStoriesRowView(containerId: string, categories?: string[]). To
show Stories from specific Categories only, pass their IDs:
initialize returns a promise that rejects when the SDK can't start. Catch the
error and show a fallback in your page. Without top-level await, use an
async function:
asyncfunctioninitializeStoryteller(){try{awaitStoryteller.sharedInstance.initialize('demo-api-key');// Create Storyteller views here.}catch(error){console.error('Storyteller could not start.',error);}}initializeStoryteller();
You can also handle the promise directly:
Storyteller.sharedInstance.initialize('demo-api-key').then(()=>{// Create Storyteller views here.}).catch((error)=>{console.error('Storyteller could not start.',error);});
The promise rejects with an Error whose message starts with the error type,
for example InvalidApiKeyError - The API Key provided was invalid. The SDK
doesn't export these error classes, and error.name is always "Error", so
check the start of the message, for example
error.message.startsWith('InvalidApiKeyError'):
InvalidApiKeyError: Storyteller rejected the API key (HTTP 401 or 404)
NetworkTimeoutError: a request timed out
NetworkError: a request failed, or returned an empty or malformed response
These errors come from the settings request. With the default privacy options,
initialize also requests the user's viewing history
(GET /api/UserActivity/{userId}) and waits for it. If that request fails,
initialize rejects with one of the same errors.
If you call initialize without an API key, the promise rejects with a text
message instead of an Error.
Earlier guides also listed InitializationError and JsonParseError. The SDK
reports those cases as NetworkError.
A horizontal row of Story tiles appears. Selecting a tile opens the Story
player.
To see whether the row loaded, set a delegate on the row with an
onDataLoadComplete callback:
storyRow.delegate={onDataLoadComplete:(success,error,dataCount)=>{if(success){console.log(`Loaded ${dataCount} Stories.`);}else{console.error('Stories could not load.',error?.message);}},};
success is false when the request fails or returns no Stories. When no
Stories are returned, error.message starts with EmptyResponseError.
{"slug": "quickstart", "page_title": "Show Your First Story Row", "page_url": "Quickstart/", "canonical_url": "/web/Quickstart/", "markdown": "# Show your first Story row\n\n<!-- markdownlint-disable MD033 -->\n<span id=\"quickstart-guide\"><\/span>\n\nThis quickstart shows one row of published Stories on a web page. You add a\ncontainer, initialize the SDK, create the row, and check that Stories loaded.\n[Before you start](getting-started/index.md) lists what you need.\n\n<span id=\"how-to-add-the-sdk-to-your-site\"><\/span>\n<span id=\"sdk-installation\"><\/span>\n<span id=\"npm\"><\/span>\n<span id=\"es6\"><\/span>\n<span id=\"commonjs\"><\/span>\n<span id=\"storyteller-cdn\"><\/span>\n\n## Install the SDK\n\nInstall the SDK with one of these guides, then return to this page:\n\n- [Install with a script tag](getting-started/script.md): load\n `storyteller.min.js` from the Storyteller CDN\n- [Install from npm](getting-started/npm.md): use an ES module `import` or a\n [CommonJS `require`](getting-started/npm.md#commonjs-browser-bundles)\n- [Use React or Next.js](getting-started/react-nextjs.md): initialize the SDK\n once and create the view in an effect\n\nThe steps below use the SDK as `Storyteller`. The samples use `await`, which\nworks only in JavaScript modules and inside `async` functions. In a classic\n`<script>`, wrap the code in an `async` function, as shown in\n[Handle initialization errors](#handle-initialization-errors).\n\n## Add a container\n\n```html\n<div id=\"storyteller-stories-row\" style=\"height: 200px\"><\/div>\n```\n\nThe row sizes its tiles to the container's height, so set a height on the\ncontainer. If the container has no height, the SDK uses a default tile height\n(160 px for square tiles, 120 px or 140 px for round tiles). When logging is\nenabled, it also logs a warning.\n\n!!! warning\n\n The container ID must be unique on the page and\n [follow best practices for HTML IDs](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).\n Use only ASCII letters, numbers, dashes (`-`), and underscores (`_`).\n\n<span id=\"sdk-initialization\"><\/span>\n\n## Initialize Storyteller\n\nCall `initialize` with your API key, and wait for it to resolve before you\ncreate a view:\n\n```javascript\nawait Storyteller.sharedInstance.initialize('demo-api-key');\n```\n\nReplace `demo-api-key` with your API key. If the user is signed in, pass your\nuser ID as `externalId`. With the default privacy options, the user's viewing\nhistory then follows them across browsers and devices:\n\n```javascript\nawait Storyteller.sharedInstance.initialize('demo-api-key', {\n externalId: 'your-user-id',\n});\n```\n\n[Identify and personalize users](Users.md) explains user IDs and how to change\nthe user.\n\n<span id=\"adding-a-storyteller-list\"><\/span>\n\n## Create the row\n\n```javascript\nconst storyRow = new Storyteller.StorytellerStoriesRowView(\n 'storyteller-stories-row'\n);\n```\n\nThe constructor takes the container ID and an optional list of Category IDs:\n`StorytellerStoriesRowView(containerId: string, categories?: string[])`. To\nshow Stories from specific Categories only, pass their IDs:\n\n```javascript\nconst filteredStoryRow = new Storyteller.StorytellerStoriesRowView(\n 'storyteller-stories-row',\n ['category-id']\n);\n```\n\n[Choose a view](views/index.md) lists the grid and Clips views. The\nStoryteller Web Showcase creates a row with the same\n[`StorytellerStoriesRowView` constructor](https://github.com/getstoryteller/storyteller-showcase-web/blob/11.0.0/nextjs/src/components/atoms/StorytellerRenderers/StorytellerStoriesRowView.tsx#L103).\n\n<span id=\"handling-errors\"><\/span>\n\n## Handle initialization errors\n\n`initialize` returns a promise that rejects when the SDK can't start. Catch the\nerror and show a fallback in your page. Without top-level `await`, use an\n`async` function:\n\n```javascript\nasync function initializeStoryteller() {\n try {\n await Storyteller.sharedInstance.initialize('demo-api-key');\n // Create Storyteller views here.\n } catch (error) {\n console.error('Storyteller could not start.', error);\n }\n}\n\ninitializeStoryteller();\n```\n\nYou can also handle the promise directly:\n\n```javascript\nStoryteller.sharedInstance\n .initialize('demo-api-key')\n .then(() => {\n // Create Storyteller views here.\n })\n .catch((error) => {\n console.error('Storyteller could not start.', error);\n });\n```\n\nThe promise rejects with an `Error` whose `message` starts with the error type,\nfor example `InvalidApiKeyError - The API Key provided was invalid`. The SDK\ndoesn't export these error classes, and `error.name` is always `\"Error\"`, so\ncheck the start of the message, for example\n`error.message.startsWith('InvalidApiKeyError')`:\n\n- `InvalidApiKeyError`: Storyteller rejected the API key (HTTP 401 or 404)\n- `NetworkTimeoutError`: a request timed out\n- `NetworkError`: a request failed, or returned an empty or malformed response\n\nThese errors come from the settings request. With the default privacy options,\n`initialize` also requests the user's viewing history\n(`GET /api/UserActivity/{userId}`) and waits for it. If that request fails,\n`initialize` rejects with one of the same errors.\n\nIf you call `initialize` without an API key, the promise rejects with a text\nmessage instead of an `Error`.\n\nEarlier guides also listed `InitializationError` and `JsonParseError`. The SDK\nreports those cases as `NetworkError`.\n\n## Check the result {#check-the-result}\n\nA horizontal row of Story tiles appears. Selecting a tile opens the Story\nplayer.\n\nTo see whether the row loaded, set a delegate on the row with an\n`onDataLoadComplete` callback:\n\n```javascript\nstoryRow.delegate = {\n onDataLoadComplete: (success, error, dataCount) => {\n if (success) {\n console.log(`Loaded ${dataCount} Stories.`);\n } else {\n console.error('Stories could not load.', error?.message);\n }\n },\n};\n```\n\n`success` is `false` when the request fails or returns no Stories. When no\nStories are returned, `error.message` starts with `EmptyResponseError`.\n\n| What you see | What to check |\n| --- | --- |\n| `initialize` rejects | Check the API key and the error message. See [Handle initialization errors](#handle-initialization-errors). |\n| `success` is `false` and `error.message` starts with `EmptyResponseError` | The request worked but returned no Stories. Check the Category IDs, and check that the Stories are published in the same tenant as the API key. |\n| `success` is `false` with another error | Find the failed request in the browser Network panel, and check its HTTP status. |\n| `success` is `true`, but no tiles show | Check the container's height and width, and check for page CSS that hides it. |\n\n[Troubleshoot an integration](getting-started/troubleshooting.md) covers more\nproblems.\n\n<span id=\"implementing-storyteller-callbacks\"><\/span>\n<span id=\"continue-your-integration\"><\/span>\n\n## Next steps\n\n- [Add a Story or Clips row](StorytellerRowView.md)\n- [Choose a view](views/index.md)\n- [Customize themes](Themes.md)\n- [Handle delegates and callbacks](delegates/index.md)\n\n<!-- markdownlint-enable MD033 -->\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}