Storyteller.sharedInstance is the SDK singleton. You use it to initialize the SDK, set the global delegate, theme, and privacy options, and open Stories or Clips from your own code. Storyteller.User is a second singleton that stores user attributes. The SDK creates both when the script or package loads.
The global callbacks for Stories, Clips, analytics, sharing, ads, and in-app links. Assigning an object replaces all four callbacks, so a callback that you leave out is cleared. Reading the property returns a new object that holds the current callbacks.
The global theme for every view. Pass a UiTheme or a plain object with optional light and dark themes. A view's configuration.theme overrides the global theme for that view.
Note
Each initialize call replaces the global theme with a default UiTheme. Set theme after initialize resolves, and set it again after a later initialize call, such as a user change.
The resolved global Theme for the current color scheme. The SDK picks the light or dark theme from theme, fills unset values with SDK defaults, and rebuilds it when the system color scheme changes. The value exists after initialize runs or after you assign theme.
The UiStyle of the global theme. The SDK also uses it for the players it creates for the open methods and hash URLs when no matching view exists on the page. On your pages the value is UiStyle.auto. Set a view's style with configuration.uiStyle.
Reading the property returns the effective values. When enableFunctionalCookies is false, enablePersonalization and enableStorytellerTracking read as false. Set the options before initialize when enableRemoteViewingStore must apply to the stored user ID.
Sets the API host for SDK requests in place of the default Storyteller API host. The SDK removes a trailing / and stores the value in local storage under Storyteller.customInstanceHost. The property has no getter, and no task guide covers it.
The API key from the latest initialize call. Before that call, it returns the key stored in local storage from an earlier page load, or null when no key is stored.
Sets the current user. The SDK stores a SHA-256 hash of the ID. A new ID resets the user data stored in the browser, including user attributes
null
Clears the user ID and resets the stored user data
Omitted
Keeps the stored user ID. The SDK creates a random ID when none is stored, or when apiKey differs from the previous key
When eventTrackingOptions.enableRemoteViewingStore is false, the SDK deletes the stored user ID and ignores externalId.
The call behaves as follows:
Concurrent calls with the same apiKey and externalId return the same promise. A call with different values waits for the active call to settle, then runs
After a successful call, later calls apply the new user and resolve without a new Settings request. With logging enabled, the SDK logs Storyteller has already been initialized. Reusing the existing instance.
The string Storyteller couldn't be initialized because no API key was provided.
The Settings request returns HTTP 401 or 404
An Error whose message starts with InvalidApiKeyError
The Settings request returns HTTP 408
An Error whose message starts with NetworkTimeoutError
Any other Settings failure, including an empty response
An Error whose message starts with NetworkError
User setup fails
The error from that step
The error classes are not exported. Check the message prefix to tell them apart.
try{awaitStoryteller.sharedInstance.initialize('demo-api-key',{externalId:'user-id',});}catch(error){console.error('Storyteller could not start.',error);}
Since: 11.0.0 shares one startup between concurrent matching calls
Returns the number of available Clips in a collection.
Parameter
Type
Required
Default
Description
collectionId
string
Yes
None
Clips collection ID
Waits: until an initialize call succeeds. The promise stays pending until then
Rejects: with Error('Collection is required to load Clips count') for an empty ID, and when the request fails or the response is empty or has no numeric count
The open methods show a Story or Clip player from your code. They share this behavior:
The SDK looks for the content in the views on the page. It uses only views with URLs enabled, which means the player.disableUrls or clipPlayer.disableUrls theme property is false.
When a view has the content, the SDK sets location.hash to that view's player URL, such as #top-stories/story-id.
Otherwise, the SDK loads the content from the API and opens it in a default player at #stories/... or #clips/....
The promise resolves after the SDK sets location.hash. It rejects when the SDK cannot load the content or the content does not exist.
The rejection value can be an Error or a string. Handle every rejection:
try{awaitStoryteller.sharedInstance.openStory('story-id');}catch(error){console.error('The Story could not be opened.',error);}
Call the open methods after initialize resolves. See Basename for the hash URL format.
Clip or Clip category to show first. clipId takes priority when you pass both. When the destination is missing or not found, the first Clip in the collection opens
openedReason
OpenedReason.deepLink
No
Set by the SDK
The OpenedReason reported in analytics events. OpenedReason.deepLink is the only accepted value
Rejects: when the collection cannot be loaded
Since: 10.7.0 made the method async and added destination
Opens the Clips player for a collection at the Clip with this external ID. When no view on the page has the Clip, the SDK loads collection pages until it finds the Clip, up to 100 pages.
Parameter
Type
Required
Default
Description
collectionId
string
Yes
None
Clips collection ID
externalId
string
Yes
None
Clip external ID
Rejects: when the collection cannot be loaded, or with a string message when the collection does not contain the Clip
Closes the open Story or Clip player. It has no effect when no player is open. The dismissed event reports DismissedReason.instanceMethod. A StorytellerEmbeddedClipsPlayerView ignores this call.
The declarations include requestUserActivityHistory_(): Promise<void>. It reloads the current user's activity history, a step that initialize already runs. No guide documents it, and integrations do not need to call it.
Storyteller.User stores user attributes for personalization and audience targeting. The SDK keeps them in local storage and adds them to its content requests.
Stores one attribute. An existing value for the key is replaced.
Parameter
Type
Required
Default
Description
key
string
Yes
None
Attribute name
value
string
Yes
None
Attribute value
Returns: true when the attribute is stored. undefined when eventTrackingOptions.enablePersonalization is false: the SDK does not store the attribute and logs a warning, which shows when logging is enabled. -1 when the stored value cannot be read back
Throws: Error('Key and value are required when setting user attributes') when key or value is empty
The declarations also include parseUserAttributesToQueryStringAlphabetically(): string. The SDK uses it to build request query strings from the stored attributes.
{"slug": "reference-storyteller", "page_title": "Storyteller Instance", "page_url": "reference/storyteller/", "canonical_url": "/web/reference/storyteller/", "markdown": "# Storyteller instance\n\n`Storyteller.sharedInstance` is the SDK singleton. You use it to initialize the SDK, set the global delegate, theme, and privacy options, and open Stories or Clips from your own code. `Storyteller.User` is a second singleton that stores user attributes. The SDK creates both when the script or package loads.\n\n## Members at a glance\n\n`Storyteller.sharedInstance` has these properties:\n\n| Property | Type | Access |\n| --- | --- | --- |\n| [`version`](#version) | `string` | Read |\n| [`isInitialized`](#isinitialized) | `boolean` | Read-only |\n| [`isPlayerVisible`](#isplayervisible) | `boolean` | Read-only |\n| [`delegate`](#delegate) | `IStorytellerDelegate` | Read and write |\n| [`theme`](#theme) | `Subset<IUiTheme>` | Read and write |\n| [`currentTheme`](#currenttheme) | `IStorytellerTheme` | Read-only |\n| [`uiStyle`](#uistyle) | `UiStyle` | Read-only |\n| [`eventTrackingOptions`](#eventtrackingoptions) | `StorytellerEventTrackingOptions` | Read and write |\n| [`customInstanceHost`](#custominstancehost) | `string` | Write-only |\n| [`currentApiKey`](#currentapikey) | `string` or `null` | Read-only |\n\nIt has these methods:\n\n| Method | Returns |\n| --- | --- |\n| [`initialize(apiKey, userInput?)`](#initialize) | `Promise<void>` |\n| [`getStoriesCount(categoryIds)`](#getstoriescount) | `Promise<number>` |\n| [`getClipsCount(collectionId)`](#getclipscount) | `Promise<number>` |\n| [`openStory(id)`](#openstory) | `Promise<void>` |\n| [`openStoryByExternalId(externalId)`](#openstorybyexternalid) | `Promise<void>` |\n| [`openPage(pageId)`](#openpage) | `Promise<void>` |\n| [`openCategory(categoryId, storyId?)`](#opencategory) | `Promise<void>` |\n| [`openCollection(collectionId, destination?, openedReason?)`](#opencollection) | `Promise<void>` |\n| [`openClipByExternalId(collectionId, externalId)`](#openclipbyexternalid) | `Promise<void>` |\n| [`dismissPlayer(animated)`](#dismissplayer) | `void` |\n| [`disablePlayback()`](#disableplayback) | `void` |\n| [`enablePlayback()`](#enableplayback) | `void` |\n| [`enableLogging()`](#enablelogging) | `void` |\n\n[Deprecated members](#deprecated-members) and an [internal member](#internal-members) are listed at the end of [Methods](#methods).\n\n## Properties\n\nThese properties are on `Storyteller.sharedInstance`.\n\n### `version`\n\n```typescript\nversion: string\n```\n\nThe SDK version, such as `'11.0.0'`. See [Use additional SDK methods](../AdditionalMethods.md#version).\n\n### `isInitialized`\n\n```typescript\nget isInitialized(): boolean\n```\n\n`true` after an [`initialize`](#initialize) call succeeds. Once `true`, it stays `true` for the rest of the page session, including while a later `initialize` call runs.\n\n- **Since**: 10.0.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#isinitialized)\n\n### `isPlayerVisible`\n\n```typescript\nget isPlayerVisible(): boolean\n```\n\n`true` while a Story or Clip player is open, and `false` after it is dismissed.\n\n- **Since**: 10.0.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#isplayervisible)\n\n### `delegate`\n\n```typescript\nget delegate(): IStorytellerDelegate\nset delegate(delegateObj: IStorytellerDelegate)\n```\n\nThe global callbacks for Stories, Clips, analytics, sharing, ads, and in-app links. Assigning an object replaces all four callbacks, so a callback that you leave out is cleared. Reading the property returns a new object that holds the current callbacks.\n\n```typescript\nStoryteller.sharedInstance.delegate = {\n onUserActivityOccurred: (type, data) => {\n console.log(type, data.context);\n },\n};\n```\n\n- **Type**: [`IStorytellerDelegate`](callbacks.md#istorytellerdelegate)\n- **Since**: 10.0.0 moved the delegate to the shared instance\n- **Guide**: [Handle global callbacks](../StorytellerDelegate.md#how-to-use)\n\n### `theme`\n\n```typescript\nget theme(): Subset<IUiTheme>\nset theme(theme: Subset<IUiTheme>)\n```\n\nThe global theme for every view. Pass a [`UiTheme`](types.md#uitheme) or a plain object with optional `light` and `dark` themes. A view's [`configuration.theme`](views.md#ilistconfiguration) overrides the global theme for that view.\n\n!!! note\n\n Each `initialize` call replaces the global theme with a default `UiTheme`. Set `theme` after `initialize` resolves, and set it again after a later `initialize` call, such as a user change.\n\n```typescript\nawait Storyteller.sharedInstance.initialize('demo-api-key');\n\nStoryteller.sharedInstance.theme = new Storyteller.UiTheme({\n light: { colors: { primary: '#1C62EB' } },\n});\n```\n\n- **Guide**: [Customize themes](../Themes.md)\n\n### `currentTheme`\n\n```typescript\nget currentTheme(): IStorytellerTheme\n```\n\nThe resolved global [`Theme`](types.md#theme) for the current color scheme. The SDK picks the `light` or `dark` theme from `theme`, fills unset values with SDK defaults, and rebuilds it when the system color scheme changes. The value exists after `initialize` runs or after you assign `theme`.\n\n### `uiStyle`\n\n```typescript\nget uiStyle(): UiStyle\n```\n\nThe [`UiStyle`](types.md#uistyle) of the global theme. The SDK also uses it for the players it creates for the [open methods](#open-methods) and hash URLs when no matching view exists on the page. On your pages the value is `UiStyle.auto`. Set a view's style with [`configuration.uiStyle`](views.md#ilistconfiguration).\n\n### `eventTrackingOptions`\n\n```typescript\nget eventTrackingOptions(): StorytellerEventTrackingOptions\nset eventTrackingOptions(newOptions: Partial<StorytellerEventTrackingOptions>)\n```\n\nThe privacy and tracking options. Every option defaults to `true`, and `disabledFunctionalFeatures` defaults to `[]`.\n\nAssigning an object replaces every option: a field that you leave out returns to its default. To change one option, spread the current value:\n\n```typescript\nStoryteller.sharedInstance.eventTrackingOptions = {\n ...Storyteller.sharedInstance.eventTrackingOptions,\n enableAdTracking: false,\n};\n```\n\nReading the property returns the effective values. When `enableFunctionalCookies` is `false`, `enablePersonalization` and `enableStorytellerTracking` read as `false`. Set the options before `initialize` when `enableRemoteViewingStore` must apply to the stored user ID.\n\n- **Type**: [`StorytellerEventTrackingOptions`](types.md#storytellereventtrackingoptions)\n- **Since**: 10.7.0. `enableAdTracking` was added in 10.9.0 and `enableFullVideoAnalytics` in 10.11.0\n- **Guide**: [Control privacy and tracking](../PrivacyAndTracking.md)\n\n### `customInstanceHost`\n\n```typescript\nset customInstanceHost(customInstanceHost: string)\n```\n\nSets the API host for SDK requests in place of the default Storyteller API host. The SDK removes a trailing `/` and stores the value in local storage under `Storyteller.customInstanceHost`. The property has no getter, and no task guide covers it.\n\n- **Since**: 8.0.0\n\n### `currentApiKey`\n\n```typescript\nget currentApiKey(): string | null\n```\n\nThe API key from the latest `initialize` call. Before that call, it returns the key stored in local storage from an earlier page load, or `null` when no key is stored.\n\n## Methods\n\nThese methods are on `Storyteller.sharedInstance`.\n\n### `initialize`\n\n```typescript\ninitialize(apiKey: string, userInput?: UserInput): Promise<void>\n```\n\nStarts the SDK for an API key and user. Create views after the promise resolves.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `apiKey` | `string` | Yes | None | Your Storyteller Web SDK API key |\n| `userInput` | `UserInput` | No | `{}` | User options. Pass a plain object such as `{ externalId: 'user-id' }` |\n\n`UserInput` has one optional field, `externalId`:\n\n```typescript\nclass UserInput {\n constructor(public externalId?: string | null) {}\n}\n```\n\n| `externalId` value | Result |\n| --- | --- |\n| A string | Sets the current user. The SDK stores a SHA-256 hash of the ID. A new ID resets the user data stored in the browser, including user attributes |\n| `null` | Clears the user ID and resets the stored user data |\n| Omitted | Keeps the stored user ID. The SDK creates a random ID when none is stored, or when `apiKey` differs from the previous key |\n\nWhen `eventTrackingOptions.enableRemoteViewingStore` is `false`, the SDK deletes the stored user ID and ignores `externalId`.\n\nThe call behaves as follows:\n\n- Concurrent calls with the same `apiKey` and `externalId` return the same promise. A call with different values waits for the active call to settle, then runs\n- After a successful call, later calls apply the new user and resolve without a new Settings request. With logging enabled, the SDK logs `Storyteller has already been initialized. Reusing the existing instance.`\n- The SDK records the [`sdkInitialized` activity event](../Analytics.md#sdk-initialization) after the Settings request succeeds or fails\n\nThe promise rejects with these values:\n\n| Condition | Rejection value |\n| --- | --- |\n| `apiKey` is empty and the SDK is not initialized | The string `Storyteller couldn't be initialized because no API key was provided.` |\n| The Settings request returns HTTP 401 or 404 | An `Error` whose message starts with `InvalidApiKeyError` |\n| The Settings request returns HTTP 408 | An `Error` whose message starts with `NetworkTimeoutError` |\n| Any other Settings failure, including an empty response | An `Error` whose message starts with `NetworkError` |\n| User setup fails | The error from that step |\n\nThe error classes are not exported. Check the message prefix to tell them apart.\n\n```typescript\ntry {\n await Storyteller.sharedInstance.initialize('demo-api-key', {\n externalId: 'user-id',\n });\n} catch (error) {\n console.error('Storyteller could not start.', error);\n}\n```\n\n- **Since**: 11.0.0 shares one startup between concurrent matching calls\n- **Guides**: [Show your first Story row](../Quickstart.md#initialize-storyteller), [Handle initialization errors](../Quickstart.md#handle-initialization-errors), [Identify and personalize users](../Users.md#setting-a-user-id)\n\n### `getStoriesCount`\n\n```typescript\ngetStoriesCount(categoryIds: string[]): Promise<number>\n```\n\nReturns the number of available Stories in the given categories. The SDK sends one count request per category and adds the results.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `categoryIds` | `string[]` | Yes | None | Story category IDs |\n\n- **Returns**: the total count. An empty array resolves to `0` at once, without a request\n- **Waits**: until an `initialize` call succeeds. The promise stays pending until then\n- **Rejects**: when a count request fails, or a response is empty or has no numeric count\n- **Since**: 10.13.16\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#getstoriescount)\n\n### `getClipsCount`\n\n```typescript\ngetClipsCount(collectionId: string): Promise<number>\n```\n\nReturns the number of available Clips in a collection.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `collectionId` | `string` | Yes | None | Clips collection ID |\n\n- **Waits**: until an `initialize` call succeeds. The promise stays pending until then\n- **Rejects**: with `Error('Collection is required to load Clips count')` for an empty ID, and when the request fails or the response is empty or has no numeric count\n- **Since**: 10.13.16\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#getclipscount)\n\n### Open methods\n\nThe open methods show a Story or Clip player from your code. They share this behavior:\n\n1. The SDK looks for the content in the views on the page. It uses only views with URLs enabled, which means the [`player.disableUrls`](../Themes.md#player) or [`clipPlayer.disableUrls`](../Themes.md#clip-player) theme property is `false`.\n2. When a view has the content, the SDK sets `location.hash` to that view's player URL, such as `#top-stories/story-id`.\n3. Otherwise, the SDK loads the content from the API and opens it in a default player at `#stories/...` or `#clips/...`.\n4. The promise resolves after the SDK sets `location.hash`. It rejects when the SDK cannot load the content or the content does not exist.\n\nThe rejection value can be an `Error` or a string. Handle every rejection:\n\n```typescript\ntry {\n await Storyteller.sharedInstance.openStory('story-id');\n} catch (error) {\n console.error('The Story could not be opened.', error);\n}\n```\n\nCall the open methods after `initialize` resolves. See [Basename](../StorytellerListView.md#basename) for the hash URL format.\n\n### `openStory`\n\n```typescript\nopenStory(id: string): Promise<void>\n```\n\nOpens the Story with this Story ID. The Story plays in single-Story mode.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `id` | `string` | Yes | None | Story ID |\n\n- **Rejects**: when the Story cannot be loaded, or with the string `No Story with the provided ID was found.`\n- **Since**: 10.7.0 made the method async\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#openstory)\n\n### `openStoryByExternalId`\n\n```typescript\nopenStoryByExternalId(externalId: string): Promise<void>\n```\n\nOpens the Story with this external ID. The Story plays in single-Story mode.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `externalId` | `string` | Yes | None | Story external ID |\n\n- **Rejects**: when the Story cannot be loaded, or with the string `No Story with the provided External ID was found.`\n- **Since**: 10.7.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#openstorybyexternalid)\n\n### `openPage`\n\n```typescript\nopenPage(pageId: string): Promise<void>\n```\n\nOpens the Story that contains this Page, starting at the Page.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `pageId` | `string` | Yes | None | Story Page ID |\n\n- **Rejects**: when the SDK cannot load a Story for the Page\n- **Since**: 10.7.0 made the method async\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#openpage)\n\n### `openCategory`\n\n```typescript\nopenCategory(categoryId: string, storyId?: string): Promise<void>\n```\n\nOpens the Story player for a category. On the page, the SDK uses a Stories view whose only category is `categoryId`.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `categoryId` | `string` | Yes | None | Story category ID |\n| `storyId` | `string` | No | None | Story to open first. When it is missing or not in the category, the first Story in the category opens |\n\n- **Rejects**: when the category cannot be loaded\n- **Since**: 10.7.0 made the method async\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#opencategory)\n\n### `openCollection`\n\n```typescript\nopenCollection(\n collectionId: string,\n destination?: { categoryId?: string; clipId?: string },\n openedReason?: OpenedReason.deepLink\n): Promise<void>\n```\n\nOpens the Clips player for a collection.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `collectionId` | `string` | Yes | None | Clips collection ID |\n| `destination` | `{ categoryId?: string; clipId?: string }` | No | None | Clip or Clip category to show first. `clipId` takes priority when you pass both. When the destination is missing or not found, the first Clip in the collection opens |\n| `openedReason` | `OpenedReason.deepLink` | No | Set by the SDK | The [`OpenedReason`](types.md#openedreason) reported in analytics events. `OpenedReason.deepLink` is the only accepted value |\n\n- **Rejects**: when the collection cannot be loaded\n- **Since**: 10.7.0 made the method async and added `destination`\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#opencollection)\n\n### `openClipByExternalId`\n\n```typescript\nopenClipByExternalId(collectionId: string, externalId: string): Promise<void>\n```\n\nOpens the Clips player for a collection at the Clip with this external ID. When no view on the page has the Clip, the SDK loads collection pages until it finds the Clip, up to 100 pages.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `collectionId` | `string` | Yes | None | Clips collection ID |\n| `externalId` | `string` | Yes | None | Clip external ID |\n\n- **Rejects**: when the collection cannot be loaded, or with a string message when the collection does not contain the Clip\n- **Since**: 10.7.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#openclipbyexternalid)\n\n### `dismissPlayer`\n\n```typescript\ndismissPlayer(animated: boolean): void\n```\n\nCloses the open Story or Clip player. It has no effect when no player is open. The dismissed event reports [`DismissedReason.instanceMethod`](types.md#dismissedreason). A `StorytellerEmbeddedClipsPlayerView` ignores this call.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `animated` | `boolean` | Yes | None | `true` plays the close animation |\n\n- **Since**: 10.0.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#dismissplayer)\n\n### `disablePlayback`\n\n```typescript\ndisablePlayback(): void\n```\n\nPauses the open Story player and the active Clip video. Players that open while playback is disabled stay paused.\n\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#disableplayback)\n\n### `enablePlayback`\n\n```typescript\nenablePlayback(): void\n```\n\nAllows playback again after `disablePlayback`, and resumes the open Story player and the active Clip. Playback is enabled by default.\n\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#enableplayback)\n\n### `enableLogging`\n\n```typescript\nenableLogging(): void\n```\n\nTurns on SDK info, warning, and log messages in the browser console. The SDK always writes errors to the console, with or without this call.\n\n- **Since**: 10.0.0\n- **Guide**: [Use additional SDK methods](../AdditionalMethods.md#enablelogging)\n\n### Deprecated members\n\nThese members still work in 11.0.0. Replace them with the members listed:\n\n| Member | Behavior | Replacement |\n| --- | --- | --- |\n| `openClip(id: string, onError?: (message: string) => void): void` | Opens a Clip that a Clips view on the page has loaded. Calls `onError` with a message when no view has the Clip | [`openCollection`](#opencollection) or [`openClipByExternalId`](#openclipbyexternalid) |\n| `enableEventTracking(): void` | Sets every tracking option to its default | [`eventTrackingOptions`](#eventtrackingoptions) |\n| `disableEventTracking(): void` | Sets every tracking option to its default, except `enableStorytellerTracking: false` | [`eventTrackingOptions`](#eventtrackingoptions) |\n| `get currentUserId(): string` | Always returns `''`. Deprecated in 10.11.0 | None |\n\n### Internal members\n\nThe declarations include `requestUserActivityHistory_(): Promise<void>`. It reloads the current user's activity history, a step that `initialize` already runs. No guide documents it, and integrations do not need to call it.\n\n## `Storyteller.User`\n\n`Storyteller.User` stores user attributes for personalization and audience targeting. The SDK keeps them in local storage and adds them to its content requests.\n\n```typescript\nStoryteller.User.setUserAttribute('location', 'New York');\n```\n\nSet attributes after `initialize` resolves. A new `externalId` in `initialize` clears the stored attributes. See [Identify and personalize users](../Users.md#personalization-and-targeted-stories).\n\n| Member | Returns |\n| --- | --- |\n| [`setUserAttribute(key, value)`](#setuserattribute) | `true`, `-1`, or `undefined` |\n| [`getUserAttribute(key)`](#getuserattribute) | `string` or `undefined` |\n| [`getUserAttributes()`](#getuserattributes) | `Record<string, string>` |\n| [`removeUserAttribute(key)`](#removeuserattribute) | `void` |\n| [`setLocale(locale)`](#setlocale) | `void` |\n| [`locale`](#locale) | `string` or `undefined` |\n\n### `setUserAttribute`\n\n```typescript\nsetUserAttribute(key: string, value: string): true | -1 | undefined\n```\n\nStores one attribute. An existing value for the key is replaced.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `key` | `string` | Yes | None | Attribute name |\n| `value` | `string` | Yes | None | Attribute value |\n\n- **Returns**: `true` when the attribute is stored. `undefined` when `eventTrackingOptions.enablePersonalization` is `false`: the SDK does not store the attribute and logs a warning, which shows when logging is enabled. `-1` when the stored value cannot be read back\n- **Throws**: `Error('Key and value are required when setting user attributes')` when `key` or `value` is empty\n- **Guide**: [Setting User Attributes](../Users.md#setting-user-attributes)\n\n### `getUserAttribute`\n\n```typescript\ngetUserAttribute(key: string): string | undefined\n```\n\nReturns the stored value for `key`, or `undefined` when none is stored.\n\n### `getUserAttributes`\n\n```typescript\ngetUserAttributes(): IUserAttributes\n```\n\nReturns all stored attributes as an object. `IUserAttributes` is `Record<string, string>`. Returns `{}` when none are stored.\n\n### `removeUserAttribute`\n\n```typescript\nremoveUserAttribute(key: string): void\n```\n\nRemoves one attribute.\n\n- **Guide**: [Removing User Attributes](../Users.md#removing-user-attributes)\n\n### `setLocale`\n\n```typescript\nsetLocale(locale: string): void\n```\n\nSets the Clips locale. The SDK stores it as the `stLocale` user attribute, so it follows the same rules as `setUserAttribute`.\n\n| Parameter | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `locale` | `string` | Yes | None | Language code, such as `'es'` |\n\n- **Throws**: the `setUserAttribute` error when `locale` is empty\n- **Since**: 10.2.0\n- **Guide**: [Updating the Clips locale](../Users.md#updating-the-clips-locale)\n\n### `locale`\n\n```typescript\nget locale(): string | undefined\n```\n\nThe stored `stLocale` attribute, or `undefined`.\n\nThe declarations also include `parseUserAttributesToQueryStringAlphabetically(): string`. The SDK uses it to build request query strings from the stored attributes.\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}