Skip to content

Personalization#

The Storyteller Public API supports personalization through user attributes. By passing user attributes as query parameters, you can receive content tailored to specific users based on their preferences, followed teams, favorite categories, and other custom attributes.

How Personalization Works#

When you configure audience targeting rules in the Storyteller CMS, clips can be targeted to specific user segments. By passing user attributes in your API requests, the API filters and prioritizes content that matches those attributes.

User Attributes Format#

User attributes are passed as query parameters using bracket notation:

userAttributes[attributeName]=value

Multiple Attributes#

You can pass multiple user attributes in a single request:

?userAttributes[FAVORITETEAM]=team-123&userAttributes[REGION]=us-east&userAttributes[SUBSCRIPTION]=premium

Attribute Names#

Attribute names are case-insensitive and will be normalized by the API. Common attribute patterns include:

Attribute Description Example Value
FAVORITETEAM User's primary favorite team team-123
FOLLOWEDTEAMS Teams the user follows team-123,team-456
FOLLOWEDPLAYERS Players the user follows player-789
REGION User's geographic region us-east
SUBSCRIPTION User's subscription tier premium

Custom Attributes

The attribute names above are examples. Your implementation may use different attribute names based on how audience targeting is configured in your Storyteller CMS.

Code Examples#

const apiKey = 'your-api-key-here';
const baseUrl = 'https://api.usestoryteller.com';

async function getPersonalizedClips(collectionId, userAttributes = {}) {
  const params = new URLSearchParams({
    'x-storyteller-api-key': apiKey,
    'ClientPlatform': 'web',
    'ClientVersion': '11.0.0',
    'pageNumber': '0'
  });

  // Add user attributes
  for (const [key, value] of Object.entries(userAttributes)) {
    params.set(`userAttributes[${key}]`, value);
  }

  const response = await fetch(
    `${baseUrl}/api/app/clips/${collectionId}/clips/paged?${params}`,
    { method: 'GET' }
  );

  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }

  return await response.json();
}

// Usage
const clips = await getPersonalizedClips('featured-clips', {
  FAVORITETEAM: 'team-123',
  REGION: 'us-east',
  SUBSCRIPTION: 'premium'
});
import requests

api_key = 'your-api-key-here'
base_url = 'https://api.usestoryteller.com'

def get_personalized_clips(
    collection_id: str,
    user_attributes: dict = None,
    page_number: int = 0
) -> dict:
    """
    Retrieve personalized clips based on user attributes.

    Args:
        collection_id: The collection identifier
        user_attributes: Dictionary of user attributes for personalization
        page_number: Page number (0-indexed)

    Returns:
        Dictionary containing personalized clips
    """
    params = {
        'x-storyteller-api-key': api_key,
        'ClientPlatform': 'android',
        'ClientVersion': '11.0.0',
        'pageNumber': page_number
    }

    # Add user attributes with bracket notation
    if user_attributes:
        for key, value in user_attributes.items():
            params[f'userAttributes[{key}]'] = value

    response = requests.get(
        f'{base_url}/api/app/clips/{collection_id}/clips/paged',
        params=params,
        timeout=30
    )
    response.raise_for_status()
    return response.json()

# Usage
clips = get_personalized_clips(
    'featured-clips',
    user_attributes={
        'FAVORITETEAM': 'team-123',
        'FOLLOWEDTEAMS': 'team-456,team-789',
        'REGION': 'us-east'
    }
)
print(f"Personalized clips: {len(clips['clips'])}")
using System.Net.Http;
using System.Text.Json;
using System.Web;

public class StorytellerClient : IDisposable
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://api.usestoryteller.com";
    private readonly string _apiKey;
    private readonly string _platform;

    public StorytellerClient(string apiKey, string platform)
    {
        _apiKey = apiKey;
        _platform = platform;
        _httpClient = new HttpClient();
    }

    public async Task<JsonDocument> GetPersonalizedClipsAsync(
        string collectionId,
        Dictionary<string, string>? userAttributes = null,
        int pageNumber = 0)
    {
        var queryParams = HttpUtility.ParseQueryString(string.Empty);
        queryParams["x-storyteller-api-key"] = _apiKey;
        queryParams["ClientPlatform"] = _platform;
        queryParams["ClientVersion"] = "11.0.0";
        queryParams["pageNumber"] = pageNumber.ToString();

        // Add user attributes with bracket notation
        if (userAttributes != null)
        {
            foreach (var attr in userAttributes)
            {
                queryParams[$"userAttributes[{attr.Key}]"] = attr.Value;
            }
        }

        var response = await _httpClient.GetAsync(
            $"{_baseUrl}/api/app/clips/{collectionId}/clips/paged?{queryParams}");

        response.EnsureSuccessStatusCode();
        var json = await response.Content.ReadAsStringAsync();
        return JsonDocument.Parse(json);
    }

    public void Dispose()
    {
        _httpClient?.Dispose();
    }
}

// Usage
using var client = new StorytellerClient("your-api-key", "ios");

var userAttributes = new Dictionary<string, string>
{
    { "FAVORITETEAM", "team-123" },
    { "FOLLOWEDTEAMS", "team-456,team-789" },
    { "SUBSCRIPTION", "premium" }
};

var clips = await client.GetPersonalizedClipsAsync(
    "featured-clips",
    userAttributes);
# Get personalized clips with user attributes
curl -X GET "https://api.usestoryteller.com/api/app/clips/featured-clips/clips/paged?x-storyteller-api-key=your-api-key-here&ClientPlatform=ios&ClientVersion=11.0.0&pageNumber=0&userAttributes[FAVORITETEAM]=team-123&userAttributes[REGION]=us-east"

# Multiple followed teams (comma-separated value)
curl -X GET "https://api.usestoryteller.com/api/app/clips/featured-clips/clips/paged?x-storyteller-api-key=your-api-key-here&ClientPlatform=ios&ClientVersion=11.0.0&pageNumber=0&userAttributes[FOLLOWEDTEAMS]=team-123,team-456,team-789"

Attribute Value Formats#

Single Values#

For attributes with a single value:

userAttributes[FAVORITETEAM]=team-123

Multiple Values#

For attributes that support multiple values, use comma-separated values:

userAttributes[FOLLOWEDTEAMS]=team-123,team-456,team-789