Skip to content

Privacy and Tracking#

The eventTrackingOptions parameter customizes Storyteller's analytics and tracking behavior. It allows certain features to be disabled based on user privacy choices. It is an object of type StorytellerEventTrackingOptions. Be explicit about privacy choices: omitting the object and constructing it with defaults produce different full-video-analytics settings in the current Flutter bridge.

Option StorytellerEventTrackingOptions() default Omitted eventTrackingOptions
enablePersonalization true true
enableStorytellerTracking true true
enableUserActivityTracking true true
enableAdTracking true true
enableFullVideoAnalytics false true
enableRemoteViewingStore true true
disabledFeatures [] []

These values were audited against a pre-release 12.1.2 Flutter wrapper with Android 12.1.2 and iOS 11.8.0. Published Flutter 12.2.0 uses Android 12.2.0 and iOS 11.9.1; see Changelog for released dependencies.

Important: eventTrackingOptions can only be set during SDK initialization. To configure tracking options, pass a StorytellerEventTrackingOptions object to the initialize method:

// Using custom tracking options
final trackingOptions = StorytellerEventTrackingOptions(
  enablePersonalization: false,
  enableStorytellerTracking: false,
  enableUserActivityTracking: false,
  enableAdTracking: false,
  enableFullVideoAnalytics: false,
  enableRemoteViewingStore: false,
  disabledFeatures: [], // empty list means no features disabled
);

final initResult = await Storyteller.initialize(
  'your-api-key',
  externalId: 'user-id',
  eventTrackingOptions: trackingOptions,
);

if (!initResult.success) {
  // Handle initialization failure
}

If you do not need custom tracking options, omit eventTrackingOptions (all tracking enabled):

await Storyteller.initialize(
  'your-api-key',
  externalId: 'user-id',
);

The Showcase StorytellerService.initialize wraps this pattern so environment secrets, user IDs, and tracking preferences are applied consistently before any widgets render.

The options remain publicly readable via Storyteller.eventTrackingOptions(), but have no separate Flutter runtime setter. To apply new choices, reinitialize with an explicit options object, await the result and handle failure before mounting or reloading content.

Example: Reading Current Tracking Options

final options = await Storyteller.eventTrackingOptions();
print('Personalization enabled: ${options.enablePersonalization}');
print('Ad tracking enabled: ${options.enableAdTracking}');
print('Disabled features: ${options.disabledFeatures}');

User Personalization#

When enablePersonalization is enabled, eligible content requests can include custom attributes. User identity on content requests also requires enableRemoteViewingStore; enabling personalization alone does not override that privacy choice.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enablePersonalization: true, // Enable personalized content
);

await Storyteller.initialize(
  'your-api-key',
  externalId: 'user-123',
  eventTrackingOptions: trackingOptions,
);

Storyteller Tracking#

When enableStorytellerTracking is enabled, we will record analytics events on our servers. Note that some events are necessary for user functionality and will still be transmitted (but not stored) even when this setting is off.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enableStorytellerTracking: false, // Disable server-side analytics
);

User Activity Tracking#

When enableUserActivityTracking is enabled, the SDK will emit events through the onUserActivityOccurred stream, which allows integrating apps to record our analytics events on their own systems.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enableUserActivityTracking: true, // Enable client-side analytics events
);

await Storyteller.initialize(
  'your-api-key',
  eventTrackingOptions: trackingOptions,
);

// Listen to analytics events
Storyteller.onUserActivityOccurred.listen((event) {
  print('Event: ${event.type}');
  // Forward to your analytics system
});

Ads Tracking#

When enableAdTracking is disabled, ad-related events will not be tracked through the onUserActivityOccurred stream and on our servers. Additionally, only necessary fields like Ad Unit Id and Custom Template Id's will be included in GAM requests.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enableAdTracking: false, // Disable ad tracking
);

Videos Tracking#

When enableFullVideoAnalytics is disabled, sensitive video event data for Story ID, Page ID, Story Title, Page Title, Clip ID, Clip Title, Story Display Title, Item Title, Container Title, Card Id, Card Title and Card Subtitle will not be included in the onUserActivityOccurred stream events.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enableFullVideoAnalytics: false, // Exclude sensitive video metadata
);

Remote Viewing Store#

When enableRemoteViewingStore is disabled, native SDKs omit user identity from content requests and remote analytics identity, and do not fetch remote user viewing history. It is independent from analytics collection: use enableStorytellerTracking, enableUserActivityTracking, and enableFullVideoAnalytics for their respective gates. iOS also clears its stored user identity; Android can retain a hashed local identity for local state. This option does not by itself disable networking or every analytics event.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  enableRemoteViewingStore: false, // Keep viewing data local only
);

Independent Functional Behavior Toggles#

The disabledFeatures property allows you to conditionally disable functional features of the SDK for privacy compliance. When a feature is disabled, the SDK will behave as if that functionality is disabled from the server.

Available features to disable:

  • 'pageReadStatus'
  • 'clipViewedStatus'
  • 'pollVotes' (iOS only in the current Flutter bridge)
  • 'triviaQuizAnswers' (iOS only in the current Flutter bridge)
  • 'clipLikes'
  • 'clipShares'

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['clipLikes', 'clipShares', 'pollVotes'],
);

pageReadStatus#

Summary: Controls whether read/unread status is enabled for Story pages.

When disabled, the SDK will not store read/unread behavior for pages. All Lists and Players will act as if read/unread tracking is disabled from the server, meaning users will not see visual indicators of which Stories they have previously viewed.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['pageReadStatus'],
);

clipViewedStatus#

Summary: Controls whether viewed/not viewed status is enabled for individual Clips.

When disabled, the SDK will not store viewed/not viewed information for Clips. All Lists and Players will act as if viewed/not viewed tracking is disabled from the server, removing visual indicators of previously watched content.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['clipViewedStatus'],
);

pollVotes#

Summary: Controls whether Poll voting responses are persistently stored on iOS. The current Android Flutter bridge ignores pollVotes.

When disabled, users can still interact with Polls and see immediate UI updates when they vote, but their votes are not persistently stored. If they navigate away and return to the same Poll, they can vote again. On iOS, this feature also suppresses the poll-vote event sent to Storyteller. This toggle is independent of enableStorytellerTracking; setting one does not automatically set the other.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['pollVotes'],
);

triviaQuizAnswers#

Summary: Controls whether Trivia Quiz responses and progress are persistently stored on iOS. The current Android Flutter bridge ignores triviaQuizAnswers.

When disabled, users can still answer trivia questions and see immediate UI feedback, but their answers are not persistently stored. If they navigate away and return to the same Quiz, they can answer questions again. The results page will be hidden since the SDK is not allowed to display persistent Quiz results.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['triviaQuizAnswers'],
);

clipLikes#

Summary: Controls whether Clip like/unlike interactions are persistently stored.

When disabled, users can still tap to like/unlike Clips and see immediate UI updates, but these interactions are not persistently stored. If they swipe away and return to the same Clip, its temporary like state returns to the state it had before that interaction.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['clipLikes'],
);

clipShares#

Summary: Disables Clip Share tracking and storage (but not the sharing action itself).

When disabled, users can still tap on Share Clip button and see immediate UI updates, but this interaction is not persistently stored. If they swipe away and returns to the same Clip, the original share count will be displayed.

Example:

final trackingOptions = StorytellerEventTrackingOptions(
  disabledFeatures: ['clipShares'],
);

Unknown disabledFeatures strings are ignored by the native bridges. Read the options back after initialization and use only the supported identifiers above. See Analytics for event payloads, Users for user changes, and Troubleshooting for initialization failures.