One of the features of Storyteller is the ability to set custom attributes for requests. Use attributes agreed with your Storyteller content configuration for audience targeting, personalization and analytics context.
To set a custom attribute, you can use the setCustomAttribute() method of the StorytellerSdk object. This method takes two parameters: the key of the custom attribute and its value. For example, to set a custom attribute for the user's location, you can use the following code:
This stores the attribute for SDK requests that use user attributes. Attribute values do not change the app’s device location or system settings.
Custom attribute values must be strings. Convert non-string values to strings before setting them. Use consistent lowercase keys across platforms: iOS normalizes keys to lowercase, while Android preserves their case. Use setLocale() for the reserved locale attribute.
To retrieve all custom attributes, you can use the customAttributes() method. This method returns a Promise that resolves to an object containing all custom attributes:
try{constattributes=awaitStorytellerSdk.customAttributes();console.log(attributes);// { location: "New York", age: "25", isPremium: "true" }}catch(error){console.error('Failed to get custom attributes:',error);}
To remove a custom attribute, you can use the removeCustomAttribute() method of the StorytellerSdk object. This method takes one parameter: the key of the custom attribute to remove. For example, to remove the custom attribute for the user's location, you can use the following code:
Storyteller provides a mechanism for managing followed categories associated with Clips. These are content category identifiers, not arbitrary custom-attribute keys. The tenant must be configured for the integrating app to manage following; app mutation methods have no effect when Storyteller manages following. On Android, setFollowedCategories() also requires personalization to be enabled.
To set a followed category, call the addFollowedCategory() function for a singular category or addFollowedCategories() for a collection. Access these methods through the StorytellerSdk object. For instance, to designate a followed category attribute for the user, implement the following code:
The native SDK resolves category metadata and updates follow state and personalization attributes. Use identifiers from your followable-category catalog. Unknown category identifiers can be omitted from a replacement.
Manage followed categories after initialization. The add/remove helpers return void while native work runs asynchronously; do not use their return as a completion signal. Use the awaited replacement method when content refresh must follow the completed update.
When your app owns the complete followed-category list, use setFollowedCategories() to replace the current set atomically. The Promise resolves after native category metadata and personalization state have been updated, so it can be awaited before reloading content:
try{awaitStorytellerSdk.setFollowedCategories(['team-id','league-id']);}catch(error){console.error('Failed to replace followed categories',error);}
Passing an empty array clears the app-managed followed set when the configuration requirements above are met. The Promise can resolve without changing anything when app-managed following is disabled (or Android personalization is disabled). Use the existing add/remove helpers for incremental changes.
To remove a followed category, utilize the removeFollowedCategory() method of the StorytellerSdk object. This method requires a single parameter—the key of the followed category to be removed. For example, to remove a followable category for a team, utilize the following code:
StorytellerSdk.removeFollowedCategory('team-id');
This function accepts a singular string parameter, removing the specified category from the locally stored list.
To remove multiple followed categories at once, use removeFollowedCategories():
To get a list of currently followed categories, utilize the followedCategories() method. This method returns a Promise that resolves to an array of followed category strings:
try{constcategories=awaitStorytellerSdk.followedCategories();console.log(`Followed categories: ${categories}`);}catch(error){console.error('Failed to get followed categories:',error);}
To fetch the backend-backed category catalog with current follow state, use getFollowableCategories(). This is useful when building your own category management UI:
importtype{StorytellerFollowableCategories,StorytellerFollowableCategory,StorytellerFollowableCategoryPlacement,}from'@getstoryteller/react-native-storyteller-sdk';try{const{categories}:StorytellerFollowableCategories=awaitStorytellerSdk.getFollowableCategories();categories.forEach(category=>{console.log(category.id,category.displayTitle??category.name,category.isFollowed);});}catch(error){console.error('Failed to get followable categories:',error);}
Each category can include id, name, displayTitle, externalId, type, placement, thumbnailUrl, and isFollowed.
StorytellerFollowableCategory and StorytellerFollowableCategoryPlacement are exported for apps that store or render this metadata. The category string fields are optional because the native iOS and Android models have different nullability guarantees; always use id as the stable required identifier.
Followed categories can be updated as a result of user actions from within the Storyteller SDK. You can listen to these event updates through the categoryFollowActionTaken event emitter:
On iOS 11.6.0+, the event's category.description field is included when the backend supplies a category description. The field is optional so existing integrations and categories without descriptions remain unchanged.
import{useEffect}from'react';importStorytellerSdkfrom'@getstoryteller/react-native-storyteller-sdk';functionMyComponent(){useEffect(()=>{constsubscription=StorytellerSdk.categoryFollowActionTaken(event=>{console.log('Category:',event.category.name);console.log('Is Following:',event.isFollowing);// Handle the follow/unfollow action});return()=>{subscription.remove();};},[]);returnnull;// Render your app UI here.}
{"slug": "user-customization", "page_title": "User Customization", "page_url": "UserCustomization/", "canonical_url": "/react-native/UserCustomization/", "markdown": "# Custom Attributes\n\nOne of the features of Storyteller is the ability to set custom attributes for requests. Use attributes agreed with your Storyteller content configuration for audience targeting, personalization and analytics context.\n\n## How to Use\n\n### Set custom attribute\n\nTo set a custom attribute, you can use the `setCustomAttribute()` method of the `StorytellerSdk` object. This method takes two parameters: the key of the custom attribute and its value. For example, to set a custom attribute for the user's location, you can use the following code:\n\n```js\nStorytellerSdk.setCustomAttribute('location', 'New York');\n```\n\nThis stores the attribute for SDK requests that use user attributes. Attribute values do not change the app\u2019s device location or system settings.\n\nCustom attribute values must be strings. Convert non-string values to strings before setting them. Use consistent lowercase keys across platforms: iOS normalizes keys to lowercase, while Android preserves their case. Use `setLocale()` for the reserved locale attribute.\n\n```js\n// String values only\nStorytellerSdk.setCustomAttribute('location', 'New York');\nStorytellerSdk.setCustomAttribute('age', String(25));\nStorytellerSdk.setCustomAttribute('isPremium', String(true));\n```\n\n> Setting custom attributes should be done after the Storyteller SDK is initialized.\n\n### Replace custom attributes\n\nTo replace the full custom attribute map, use `setCustomAttributes()` with string keys and values:\n\n```js\nStorytellerSdk.setCustomAttributes({\n location: 'New York',\n tier: 'premium',\n});\n```\n\n### Get custom attributes\n\nTo retrieve all custom attributes, you can use the `customAttributes()` method. This method returns a Promise that resolves to an object containing all custom attributes:\n\n```js\ntry {\n const attributes = await StorytellerSdk.customAttributes();\n console.log(attributes); // { location: \"New York\", age: \"25\", isPremium: \"true\" }\n} catch (error) {\n console.error('Failed to get custom attributes:', error);\n}\n```\n\n### Remove custom attribute\n\nTo remove a custom attribute, you can use the `removeCustomAttribute()` method of the `StorytellerSdk` object. This method takes one parameter: the key of the custom attribute to remove. For example, to remove the custom attribute for the user's location, you can use the following code:\n\n```js\nStorytellerSdk.removeCustomAttribute('location');\n```\n\n## Best Practices\n\n- **Timing**: Set custom attributes after SDK initialization and before loading any content views\n- **Privacy**: Ensure custom attributes comply with your privacy policy and relevant regulations (GDPR, CCPA, etc.)\n- **Size**: Keep values small and relevant to your content configuration\n\n## Followable Categories\n\nStoryteller provides a mechanism for managing followed categories associated with Clips. These are content category identifiers, not arbitrary custom-attribute keys. The tenant must be configured for the integrating app to manage following; app mutation methods have no effect when Storyteller manages following. On Android, `setFollowedCategories()` also requires personalization to be enabled.\n\n### How to Use\n\n#### Set followed categories\n\nTo set a followed category, call the `addFollowedCategory()` function for a singular category or `addFollowedCategories()` for a collection. Access these methods through the `StorytellerSdk` object. For instance, to designate a followed category attribute for the user, implement the following code:\n\n```js\nStorytellerSdk.addFollowedCategory('team-id');\n```\n\nor\n\n```js\nStorytellerSdk.addFollowedCategories(['team-id', 'league-id']);\n```\n\nThe native SDK resolves category metadata and updates follow state and personalization attributes. Use identifiers from your followable-category catalog. Unknown category identifiers can be omitted from a replacement.\n\n> Manage followed categories after initialization. The add/remove helpers return `void` while native work runs asynchronously; do not use their return as a completion signal. Use the awaited replacement method when content refresh must follow the completed update.\n\nWhen your app owns the complete followed-category list, use `setFollowedCategories()` to replace the current set atomically. The Promise resolves after native category metadata and personalization state have been updated, so it can be awaited before reloading content:\n\n```js\ntry {\n await StorytellerSdk.setFollowedCategories(['team-id', 'league-id']);\n} catch (error) {\n console.error('Failed to replace followed categories', error);\n}\n```\n\nPassing an empty array clears the app-managed followed set when the configuration requirements above are met. The Promise can resolve without changing anything when app-managed following is disabled (or Android personalization is disabled). Use the existing add/remove helpers for incremental changes.\n\n#### Remove followable category\n\nTo remove a followed category, utilize the `removeFollowedCategory()` method of the `StorytellerSdk` object. This method requires a single parameter\u2014the key of the followed category to be removed. For example, to remove a followable category for a team, utilize the following code:\n\n```js\nStorytellerSdk.removeFollowedCategory('team-id');\n```\n\nThis function accepts a singular string parameter, removing the specified category from the locally stored list.\n\nTo remove multiple followed categories at once, use `removeFollowedCategories()`:\n\n```js\nStorytellerSdk.removeFollowedCategories(['team-id', 'league-id']);\n```\n\n#### Check if a category is followed\n\nTo check whether a category is currently followed, use `isCategoryFollowed()`:\n\n```js\nconst isFollowing = StorytellerSdk.isCategoryFollowed('team-id');\n```\n\n#### Get followed categories\n\nTo get a list of currently followed categories, utilize the `followedCategories()` method. This method returns a Promise that resolves to an array of followed category strings:\n\n```js\ntry {\n const categories = await StorytellerSdk.followedCategories();\n console.log(`Followed categories: ${categories}`);\n} catch (error) {\n console.error('Failed to get followed categories:', error);\n}\n```\n\n#### Get followable categories\n\nTo fetch the backend-backed category catalog with current follow state, use `getFollowableCategories()`. This is useful when building your own category management UI:\n\n```typescript\nimport type {\n StorytellerFollowableCategories,\n StorytellerFollowableCategory,\n StorytellerFollowableCategoryPlacement,\n} from '@getstoryteller/react-native-storyteller-sdk';\n\ntry {\n const { categories }: StorytellerFollowableCategories = await StorytellerSdk.getFollowableCategories();\n categories.forEach(category => {\n console.log(category.id, category.displayTitle ?? category.name, category.isFollowed);\n });\n} catch (error) {\n console.error('Failed to get followable categories:', error);\n}\n```\n\nEach category can include `id`, `name`, `displayTitle`, `externalId`, `type`, `placement`, `thumbnailUrl`, and `isFollowed`.\n\n`StorytellerFollowableCategory` and `StorytellerFollowableCategoryPlacement` are exported for apps that store or render this metadata. The category string fields are optional because the native iOS and Android models have different nullability guarantees; always use `id` as the stable required identifier.\n\n#### Get updates about followed categories\n\nFollowed categories can be updated as a result of user actions from within the Storyteller SDK. You can listen to these event updates through the `categoryFollowActionTaken` event emitter:\n\nOn iOS 11.6.0+, the event's `category.description` field is included when the backend supplies a category description. The field is optional so existing integrations and categories without descriptions remain unchanged.\n\n```js\nimport { useEffect } from 'react';\nimport StorytellerSdk from '@getstoryteller/react-native-storyteller-sdk';\n\nfunction MyComponent() {\n useEffect(() => {\n const subscription = StorytellerSdk.categoryFollowActionTaken(event => {\n console.log('Category:', event.category.name);\n console.log('Is Following:', event.isFollowing);\n\n // Handle the follow/unfollow action\n });\n\n return () => {\n subscription.remove();\n };\n }, []);\n\n return null; // Render your app UI here.\n}\n```\n\nFor more details, see [Storyteller Event Handlers](Storyteller.md#event-handling).\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}