From ac80b531c5c2437c770ac9e1200ac317c62c02cf Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Fri, 26 Sep 2025 15:36:42 -0700 Subject: [PATCH 01/13] Feature flag SDK public docs --- .../tracking-methods/sdks/android/_meta.ts | 3 +- .../sdks/android/android-flags.mdx | 271 ++++++++++++++++++ .../tracking-methods/sdks/javascript/_meta.ts | 3 +- .../sdks/javascript/javascript-flags.mdx | 125 ++++++++ .../docs/tracking-methods/sdks/swift/_meta.ts | 3 +- .../sdks/swift/swift-flags.mdx | 243 ++++++++++++++++ 6 files changed, 645 insertions(+), 3 deletions(-) create mode 100644 pages/docs/tracking-methods/sdks/android/android-flags.mdx create mode 100644 pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx create mode 100644 pages/docs/tracking-methods/sdks/swift/swift-flags.mdx diff --git a/pages/docs/tracking-methods/sdks/android/_meta.ts b/pages/docs/tracking-methods/sdks/android/_meta.ts index 3ab8f090a1..1b3048fb6b 100644 --- a/pages/docs/tracking-methods/sdks/android/_meta.ts +++ b/pages/docs/tracking-methods/sdks/android/_meta.ts @@ -1,3 +1,4 @@ export default { - "android-replay": "Session Replay (Android)" + "android-replay": "Session Replay (Android)", + "android-flags": "Feature Flags (Javascript)" } diff --git a/pages/docs/tracking-methods/sdks/android/android-flags.mdx b/pages/docs/tracking-methods/sdks/android/android-flags.mdx new file mode 100644 index 0000000000..b383549b89 --- /dev/null +++ b/pages/docs/tracking-methods/sdks/android/android-flags.mdx @@ -0,0 +1,271 @@ +import { Callout } from 'nextra/components' + +# Implement Feature Flags (Android) + +## Overview + +This developer guide will assist you in configuring your Android platform for Feature Flags using the [Mixpanel Android SDK](/docs/tracking-methods/sdks/android). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. + +For complete Android SDK documentation, see the [Android SDK guide](/docs/tracking-methods/sdks/android). + +## Prerequisites + +Before implementing Feature Flags, ensure: + +- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v7.0.0`](https://github.com/mixpanel/mixpanel-android/releases/tag/v7.0.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) + +## Flag Initialization + +Initializing the SDK with feature flags enabled requires setting the `featureFlagsEnabled` option to `true` in MixpanelOptions. This enables making an outbound request to Mixpanel servers with the current user context. +The server will assign the user context to a variant for each feature flag according to how they are configured in the Mixpanel UX. + +The response will include an assigned variant for each flag that the user context is in a rollout group for. If a flag is not returned, it most likely signifies that the user was either not in the rollout percentage for a flag or in the configured targeting cohort. + +**Example Usage** + +```java +MixpanelOptions options = new MixpanelOptions(); +options.featureFlagsEnabled = true; + +MixpanelAPI mixpanel = MixpanelAPI.getInstance(context, "YOUR_PROJECT_TOKEN", options); +``` + +If your flag is configured with a Variant Assignment Key other than `distinct_id` for any of the feature flags in your project, then the call to initialize feature flags must include those keys. + +For example, for a Variant Assignment Key, `company_id`, you would setup the SDK as follows: + +```java +JSONObject context = new JSONObject(); +context.put("company_id", "X"); + +MixpanelOptions options = new MixpanelOptions(); +options.featureFlagsEnabled = true; +options.featureFlagsContext = context; + +MixpanelAPI mixpanel = MixpanelAPI.getInstance(getApplicationContext(), "YOUR_PROJECT_TOKEN", options); +``` + +If you are using Runtime Targeting in any of the feature flags in your project, then any properties that you use in targeting should be included in a `customProperties` node within the context: + +```java +JSONObject customProperties = new JSONObject(); +customProperties.put("platform", "android"); + +JSONObject context = new JSONObject(); +context.put("company_id", "X"); +context.put("customProperties", customProperties); + +MixpanelOptions options = new MixpanelOptions(); +options.featureFlagsEnabled = true; +options.featureFlagsContext = context; + +MixpanelAPI mixpanel = MixpanelAPI.getInstance(getApplicationContext(), "YOUR_PROJECT_TOKEN", options); +``` + +## Flag Reload + +Following initialization, you can reload feature flag assignments in a couple of ways: + +1) After a user logs in or out of your application and you call `identify`, a feature flag reload will be triggered. + +```java +String updatedDistinctId = ""; +mixpanel.identify(updatedDistinctId); +``` + +2) If variant assignment keys or properties used in Runtime Targeting change during the lifetime of your application, you can manually reload flags by updating the context: + +```java +JSONObject newCustomProperties = new JSONObject(); +newCustomProperties.put("platform", "android"); + +JSONObject newContext = new JSONObject(); +newContext.put("company_id", "Y"); +newContext.put("customProperties", newCustomProperties); + +// Update the context and reload flags +mixpanel.getOptions().featureFlagsContext = newContext; +mixpanel.getFlags().loadFlags(); +``` + +## Flag Evaluation + +Lookup the assigned value for a feature flag. +This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. + +### Synchronous Flag Retrieval + +**Get Flag Variant** + +```java +// Get the complete variant object synchronously +MixpanelFlagVariant fallbackVariant = new MixpanelFlagVariant("control", "control"); +MixpanelFlagVariant variant = mixpanel.getFlags().getVariantSync("my-feature-flag", fallbackVariant); + +// Use flag variant in your application logic +if ("variant_a".equals(variant.key)) { + showExperimentForVariantA(); +} else if ("variant_b".equals(variant.key)) { + showExperimentForVariantB(); +} else { + showDefaultExperience(); +} +``` + +**Get Flag Value** + +```java +// Get just the flag value synchronously +Object flagValue = mixpanel.getFlags().getVariantValueSync("my-feature-flag", "control"); + +// Use flag value in your application logic +if ("variant_a".equals(flagValue)) { + showExperimentForVariantA(); +} else if ("variant_b".equals(flagValue)) { + showExperimentForVariantB(); +} else { + showDefaultExperience(); +} +``` + +**Check if Flag is Enabled** + +```java +// Check if a boolean flag is enabled synchronously +boolean isEnabled = mixpanel.getFlags().isEnabledSync("my-boolean-flag", false); + +if (isEnabled) { + showNewFeature(); +} else { + showOldFeature(); +} +``` + +### Asynchronous Flag Retrieval + +**Get Flag Variant** + +```java +// Get the complete variant object asynchronously +MixpanelFlagVariant fallbackVariant = new MixpanelFlagVariant("control", "control"); +mixpanel.getFlags().getVariant("my-feature-flag", fallbackVariant, new FlagCompletionCallback() { + @Override + public void onComplete(MixpanelFlagVariant variant) { + // This runs on the main thread + if ("variant_a".equals(variant.key)) { + showExperimentForVariantA(); + } else if ("variant_b".equals(variant.key)) { + showExperimentForVariantB(); + } else { + showDefaultExperience(); + } + } +}); +``` + +**Get Flag Value** + +```java +// Get just the flag value asynchronously +mixpanel.getFlags().getVariantValue("my-feature-flag", "control", new FlagCompletionCallback() { + @Override + public void onComplete(Object value) { + // This runs on the main thread + if ("variant_a".equals(value)) { + showExperimentForVariantA(); + } else if ("variant_b".equals(value)) { + showExperimentForVariantB(); + } else { + showDefaultExperience(); + } + } +}); +``` + +**Check if Flag is Enabled** + +```java +// Check if a boolean flag is enabled asynchronously +mixpanel.getFlags().isEnabled("my-boolean-flag", false, new FlagCompletionCallback() { + @Override + public void onComplete(Boolean isEnabled) { + // This runs on the main thread + if (isEnabled) { + showNewFeature(); + } else { + showOldFeature(); + } + } +}); +``` + +## FAQ / Troubleshooting + +### What if I'm not receiving any flags on SDK initialization? + +1. **Check your project token**: + - Ensure you're using the correct project token from your [Mixpanel project settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) +2. **Review flag configuration**: + - Make sure your feature flag is enabled + - Check the flag's rollout percentage + - User contexts that are not assigned to the rollout percentage will not receive flags + - If you are using a targeting cohort, verify on the mixpanel 'Users' page that the user's `distinct_id` is a member of that cohort. + +3. **Review SDK parameters**: + - Ensure `featureFlagsEnabled = true` is set in MixpanelOptions + - If using a custom Variant Assignment Key, ensure it is included in the `featureFlagsContext` JSONObject + - If using Runtime Targeting, ensure all properties used in targeting are included in the `customProperties` object within `featureFlagsContext` + +4. **Check flags readiness**: Use `areFlagsReady()` to check if flags have been loaded before making synchronous calls +5. **Enable debug logging**: Check Android logs for detailed information about flag requests and responses + +### How do I check if flags are ready before making synchronous calls? + +```java +if (mixpanel.getFlags().areFlagsReady()) { + // Safe to make synchronous calls + MixpanelFlagVariant variant = mixpanel.getFlags().getVariantSync("my-flag", fallbackVariant); +} else { + // Use async calls or trigger flag loading + mixpanel.getFlags().loadFlags(); +} +``` + +### What's the difference between synchronous and asynchronous flag methods? + +- **Synchronous methods** (`getVariantSync`, `getVariantValueSync`, `isEnabledSync`): Return immediately with the cached flag value if flags are ready, or the fallback value if flags are not ready. These methods will not trigger a network request and should not be called from the main UI thread if flags might not be ready. +- **Asynchronous methods** (`getVariant`, `getVariantValue`, `isEnabled`): Will trigger a flag fetch if flags are not ready, and call the completion callback with the result once available. The completion callback runs on the main thread. + +### How do I handle flag updates during app lifecycle? + +Flag updates are automatically triggered when: +- You call `identify()` with a new distinct ID +- You manually call `loadFlags()` after updating the context + +For runtime context changes: +```java +JSONObject newContext = new JSONObject(); +newContext.put("company_id", "new_company"); + +// Update context and reload flags +mixpanel.getOptions().featureFlagsContext = newContext; +mixpanel.getFlags().loadFlags(); +``` + +### Thread Safety Considerations + +The Android SDK handles thread safety internally: +- All flag operations are thread-safe +- Synchronous methods can be called from any thread (but avoid calling from main thread if flags might not be ready) +- Asynchronous completion callbacks always run on the main thread +- Flag loading and network requests happen on background threads + +### ProGuard/R8 Configuration + +If you're using code obfuscation, ensure your ProGuard/R8 configuration preserves the necessary classes: + +``` +-keep class com.mixpanel.android.mpmetrics.MixpanelFlagVariant { *; } +-keep class com.mixpanel.android.mpmetrics.FlagCompletionCallback { *; } +``` \ No newline at end of file diff --git a/pages/docs/tracking-methods/sdks/javascript/_meta.ts b/pages/docs/tracking-methods/sdks/javascript/_meta.ts index 47ae6f8a5c..e0a438591d 100644 --- a/pages/docs/tracking-methods/sdks/javascript/_meta.ts +++ b/pages/docs/tracking-methods/sdks/javascript/_meta.ts @@ -1,3 +1,4 @@ export default { - "javascript-replay": "Session Replay (Javascript)" + "javascript-replay": "Session Replay (Javascript)", + "javascript-flags": "Feature Flags (Javascript)", } diff --git a/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx new file mode 100644 index 0000000000..ac77246768 --- /dev/null +++ b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx @@ -0,0 +1,125 @@ +import { Callout } from 'nextra/components' + +# Implement Feature Flags (Web) + +## Overview + +This developer guide will assist you in configuring your web platform for Feature Flags using the [Mixpanel JavaScript SDK](/docs/tracking-methods/sdks/javascript). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. + +For complete JavaScript SDK documentation, see the [JavaScript SDK guide](/docs/tracking-methods/sdks/javascript). + +## Prerequisites + +Before implementing Feature Flags, ensure: + +- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v2.70.0`](https://github.com/mixpanel/mixpanel-js/releases/tag/v2.70.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) + +## Flag Initialization + +Initializing the SDK with the `flags` option enables making an outbound request to Mixpanel servers with the current user context. +The server will assign the user context to a variant for each feature flag according to the how they are configured in the Mixpanel UX. + +The response will include an assigned variant for each flag that the user context is in a rollout group for. If a flag is not returned, it most likely signifies that the user was either not in the rollout percentage for a flag or in the configured targeting cohort. + +**Example Usage** + +```javascript +mixpanel.init("YOUR_PROJECT_TOKEN", { + debug: true, + flags: true, +}); +``` + +If your flag is configured with a Variant Assignment Key other than `distinct_id` for any of the feature flags in your project, then the call to initialize feature flags must include those keys. + +For example, for a Variant Assignment Key, `company_id`, you would setup the SDK as follows. + +```javascript +mixpanel.init("YOUR_PROJECT_TOKEN", { + debug: true, + flags: { + context: { + company_id: "X", + }, + }, +}); +``` + +If you are using Runtime Targeting in any of the feature flags in your project, then any properties that you use in targeting should be included in a `custom_properties` node within `context`: + +```javascript +mixpanel.init("YOUR_PROJECT_TOKEN", { + debug: true, + flags: { + context: { + company_id: "X", + custom_properties: { + platform: "web", + }, + }, + }, +}); +``` + +## Flag Reload + +Following initialization, you can reload feature flag assignments in a couple of ways: + +1) After a user logs in or out of your application and you call `identify`, a feature flag reload will be triggered. + +```javascript +updated_distinct_id = "" +mixpanel.identify(updated_distinct_id) +``` + +2) If variant assignment keys or properties used in Runtime Targeting change during the lifetime of your application, you can manually reload with those new properties + +```javascript +mixpanel.flags.update_context({ + company_id: "Y", + custom_properties: { + platform: "mobile", + }, +}); +``` + +## Flag Evaluation + +Lookup the assigned value for a feature flag. +This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. + +**Example usage** + +```javascript +// Fetch the variant value once flags are ready and track an exposure event *if* the user context is in a rollout group for the feature flag. +const variant_value = await mixpanel.flags.get_variant_value("my-feature-flag", "control"); + +// Use flag value in your application logic +if (variant_value == "variant_a") { + showExperimentForVariantA(); +} else if (variant_value == "variant_b") { + showExperienceForVariantB(); +} else if (variant_value == "control") { + showDefaultExperience(); +} +``` + +## FAQ / Troubleshooting + +### What if I'm not receiving any flags on SDK initialization? + +1. **Check your project token**: + - Ensure you're using the correct project token from your [Mixpanel project settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) +2. **Review flag configuration**: + - Make sure your feature flag is enabled + - Check the flag's rollout percentage + - User contexts that are not assigned to the rollout percentage will not + - If you are using a targeting cohort, verify on the mixpanel 'Users' page that the user's `distinct_id` is a member of that cohort. + +3. **Review SDK parameters**: + - Ensure `flags: true` or `flags: { context: {...} }` is included in the init options + - If using a custom Variant Assignment Key, ensure it is included in the `context` object + - If using Runtime Targeting, ensure all properties used in targeting are included in the `custom_properties` object within `context` + +5. **Enable debug mode**: Use `debug: true` in initialization to see detailed logs in the browser console diff --git a/pages/docs/tracking-methods/sdks/swift/_meta.ts b/pages/docs/tracking-methods/sdks/swift/_meta.ts index 1f08a36e99..cae800483b 100644 --- a/pages/docs/tracking-methods/sdks/swift/_meta.ts +++ b/pages/docs/tracking-methods/sdks/swift/_meta.ts @@ -1,3 +1,4 @@ export default { - "swift-replay": "Session Replay (Swift)" + "swift-replay": "Session Replay (Swift)", + "swift-flags": "Feature Flags (Swift)" } diff --git a/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx new file mode 100644 index 0000000000..4cb100b7f6 --- /dev/null +++ b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx @@ -0,0 +1,243 @@ +import { Callout } from 'nextra/components' + +# Implement Feature Flags (Swift) + +## Overview + +This developer guide will assist you in configuring your iOS/macOS platform for Feature Flags using the [Mixpanel Swift SDK](/docs/tracking-methods/sdks/swift). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. + +For complete Swift SDK documentation, see the [Swift SDK guide](/docs/tracking-methods/sdks/swift). + +## Prerequisites + +Before implementing Feature Flags, ensure: + +- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v4.0.0`](https://github.com/mixpanel/mixpanel-swift/releases/tag/v4.0.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) + +## Flag Initialization + +Initializing the SDK with feature flags enabled requires setting the `featureFlagsEnabled` option to `true`. This enables making an outbound request to Mixpanel servers with the current user context. +The server will assign the user context to a variant for each feature flag according to how they are configured in the Mixpanel UX. + +The response will include an assigned variant for each flag that the user context is in a rollout group for. If a flag is not returned, it most likely signifies that the user was either not in the rollout percentage for a flag or in the configured targeting cohort. + +**Example Usage** + +```swift +Mixpanel.initialize(token: "YOUR_PROJECT_TOKEN", options: MixpanelOptions( + featureFlagsEnabled: true +)) +``` + +If your flag is configured with a Variant Assignment Key other than `distinct_id` for any of the feature flags in your project, then the call to initialize feature flags must include those keys. + +For example, for a Variant Assignment Key, `company_id`, you would setup the SDK as follows: + +```swift +let options = MixpanelOptions( + featureFlagsEnabled: true, + featureFlagsContext: [ + "company_id": "X" + ] +) +Mixpanel.initialize(token: "YOUR_PROJECT_TOKEN", options: options) +``` + +If you are using Runtime Targeting in any of the feature flags in your project, then any properties that you use in targeting should be included in a `customProperties` node within the context: + +```swift +let options = MixpanelOptions( + featureFlagsEnabled: true, + featureFlagsContext: [ + "company_id": "X", + "customProperties": [ + "platform": "ios" + ] + ] +) +Mixpanel.initialize(token: "YOUR_PROJECT_TOKEN", options: options) +``` + +## Flag Reload + +Following initialization, you can reload feature flag assignments in a couple of ways: + +1) After a user logs in or out of your application and you call `identify`, a feature flag reload will be triggered. + +```swift +let updatedDistinctId = "" +Mixpanel.mainInstance().identify(distinctId: updatedDistinctId) +``` + +2) If variant assignment keys or properties used in Runtime Targeting change during the lifetime of your application, you can manually reload flags by updating the context: + +```swift +Mixpanel.mainInstance().flags.delegate?.getOptions().featureFlagsContext = [ + "company_id": "Y", + "customProperties": [ + "platform": "ios" + ] +] +Mixpanel.mainInstance().flags.loadFlags() +``` + +## Flag Evaluation + +Lookup the assigned value for a feature flag. +This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. + +### Synchronous Flag Retrieval + +**Get Flag Variant** + +```swift +// Get the complete variant object synchronously +let fallbackVariant = MixpanelFlagVariant(key: "control", value: "control") +let variant = Mixpanel.mainInstance().flags.getVariantSync("my-feature-flag", fallback: fallbackVariant) + +// Use flag variant in your application logic +if variant.key == "variant_a" { + showExperimentForVariantA() +} else if variant.key == "variant_b" { + showExperimentForVariantB() +} else { + showDefaultExperience() +} +``` + +**Get Flag Value** + +```swift +// Get just the flag value synchronously +let flagValue = Mixpanel.mainInstance().flags.getVariantValueSync("my-feature-flag", fallbackValue: "control") + +// Use flag value in your application logic +if flagValue as? String == "variant_a" { + showExperimentForVariantA() +} else if flagValue as? String == "variant_b" { + showExperimentForVariantB() +} else { + showDefaultExperience() +} +``` + +**Check if Flag is Enabled** + +```swift +// Check if a boolean flag is enabled synchronously +let isEnabled = Mixpanel.mainInstance().flags.isEnabledSync("my-boolean-flag", fallbackValue: false) + +if isEnabled { + showNewFeature() +} else { + showOldFeature() +} +``` + +### Asynchronous Flag Retrieval + +**Get Flag Variant** + +```swift +// Get the complete variant object asynchronously +let fallbackVariant = MixpanelFlagVariant(key: "control", value: "control") +Mixpanel.mainInstance().flags.getVariant("my-feature-flag", fallback: fallbackVariant) { variant in + DispatchQueue.main.async { + // Use flag variant in your application logic + if variant.key == "variant_a" { + showExperimentForVariantA() + } else if variant.key == "variant_b" { + showExperimentForVariantB() + } else { + showDefaultExperience() + } + } +} +``` + +**Get Flag Value** + +```swift +// Get just the flag value asynchronously +Mixpanel.mainInstance().flags.getVariantValue("my-feature-flag", fallbackValue: "control") { value in + DispatchQueue.main.async { + // Use flag value in your application logic + if let stringValue = value as? String { + switch stringValue { + case "variant_a": + showExperimentForVariantA() + case "variant_b": + showExperimentForVariantB() + default: + showDefaultExperience() + } + } + } +} +``` + +**Check if Flag is Enabled** + +```swift +// Check if a boolean flag is enabled asynchronously +Mixpanel.mainInstance().flags.isEnabled("my-boolean-flag", fallbackValue: false) { isEnabled in + DispatchQueue.main.async { + if isEnabled { + showNewFeature() + } else { + showOldFeature() + } + } +} +``` + +## FAQ / Troubleshooting + +### What if I'm not receiving any flags on SDK initialization? + +1. **Check your project token**: + - Ensure you're using the correct project token from your [Mixpanel project settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) +2. **Review flag configuration**: + - Make sure your feature flag is enabled + - Check the flag's rollout percentage + - User contexts that are not assigned to the rollout percentage will not receive flags + - If you are using a targeting cohort, verify on the mixpanel 'Users' page that the user's `distinct_id` is a member of that cohort. + +3. **Review SDK parameters**: + - Ensure `featureFlagsEnabled: true` is included in the MixpanelOptions + - If using a custom Variant Assignment Key, ensure it is included in the `featureFlagsContext` + - If using Runtime Targeting, ensure all properties used in targeting are included in the `customProperties` object within `featureFlagsContext` + +4. **Check flags readiness**: Use `areFlagsReady()` to check if flags have been loaded before making synchronous calls +5. **Enable debug mode**: Set up logging to see detailed information about flag requests and responses + +### How do I check if flags are ready before making synchronous calls? + +```swift +if Mixpanel.mainInstance().flags.areFlagsReady() { + // Safe to make synchronous calls + let variant = Mixpanel.mainInstance().flags.getVariantSync("my-flag", fallback: fallbackVariant) +} else { + // Use async calls or trigger flag loading + Mixpanel.mainInstance().flags.loadFlags() +} +``` + +### What's the difference between synchronous and asynchronous flag methods? + +- **Synchronous methods** (`getVariantSync`, `getVariantValueSync`, `isEnabledSync`): Return immediately with the cached flag value if flags are ready, or the fallback value if flags are not ready. These methods will not trigger a network request. +- **Asynchronous methods** (`getVariant`, `getVariantValue`, `isEnabled`): Will trigger a flag fetch if flags are not ready, and call the completion handler with the result once available. + +### How do I handle flag updates during app lifecycle? + +Flag updates are automatically triggered when: +- You call `identify()` with a new distinct ID +- You manually call `loadFlags()` after updating the context + +For runtime context changes: +```swift +// Update context and reload flags +Mixpanel.mainInstance().flags.delegate?.getOptions().featureFlagsContext["company_id"] = "new_company" +Mixpanel.mainInstance().flags.loadFlags() +``` \ No newline at end of file From 6615757be4980f39556b5e2d50f7d7a8da8a81f6 Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Fri, 26 Sep 2025 16:57:39 -0700 Subject: [PATCH 02/13] updates --- .../tracking-methods/sdks/android/_meta.ts | 2 +- .../sdks/android/android-flags.mdx | 170 +++++------------- .../sdks/javascript/javascript-flags.mdx | 20 ++- .../sdks/swift/swift-flags.mdx | 140 ++++----------- 4 files changed, 97 insertions(+), 235 deletions(-) diff --git a/pages/docs/tracking-methods/sdks/android/_meta.ts b/pages/docs/tracking-methods/sdks/android/_meta.ts index 1b3048fb6b..5ee586c759 100644 --- a/pages/docs/tracking-methods/sdks/android/_meta.ts +++ b/pages/docs/tracking-methods/sdks/android/_meta.ts @@ -1,4 +1,4 @@ export default { "android-replay": "Session Replay (Android)", - "android-flags": "Feature Flags (Javascript)" + "android-flags": "Feature Flags (Android)" } diff --git a/pages/docs/tracking-methods/sdks/android/android-flags.mdx b/pages/docs/tracking-methods/sdks/android/android-flags.mdx index b383549b89..c431477915 100644 --- a/pages/docs/tracking-methods/sdks/android/android-flags.mdx +++ b/pages/docs/tracking-methods/sdks/android/android-flags.mdx @@ -4,7 +4,7 @@ import { Callout } from 'nextra/components' ## Overview -This developer guide will assist you in configuring your Android platform for Feature Flags using the [Mixpanel Android SDK](/docs/tracking-methods/sdks/android). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. +This developer guide will assist you in configuring your Android platform for Feature Flags using the [Mixpanel Android SDK](/docs/tracking-methods/sdks/android). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. For complete Android SDK documentation, see the [Android SDK guide](/docs/tracking-methods/sdks/android). @@ -12,12 +12,12 @@ For complete Android SDK documentation, see the [Android SDK guide](/docs/tracki Before implementing Feature Flags, ensure: -- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v7.0.0`](https://github.com/mixpanel/mixpanel-android/releases/tag/v7.0.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v8.2.4`](https://github.com/mixpanel/mixpanel-android/releases/tag/v8.2.4)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Initialization -Initializing the SDK with feature flags enabled requires setting the `featureFlagsEnabled` option to `true` in MixpanelOptions. This enables making an outbound request to Mixpanel servers with the current user context. +Initializing the SDK with feature flags enabled requires setting the `featureFlagsEnabled` option to `true` in `MixpanelOptions`. This enables making an outbound request to Mixpanel servers with the current user context. The server will assign the user context to a variant for each feature flag according to how they are configured in the Mixpanel UX. The response will include an assigned variant for each flag that the user context is in a rollout group for. If a flag is not returned, it most likely signifies that the user was either not in the rollout percentage for a flag or in the configured targeting cohort. @@ -88,83 +88,14 @@ newContext.put("customProperties", newCustomProperties); mixpanel.getOptions().featureFlagsContext = newContext; mixpanel.getFlags().loadFlags(); ``` - ## Flag Evaluation Lookup the assigned value for a feature flag. -This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. - -### Synchronous Flag Retrieval - -**Get Flag Variant** - -```java -// Get the complete variant object synchronously -MixpanelFlagVariant fallbackVariant = new MixpanelFlagVariant("control", "control"); -MixpanelFlagVariant variant = mixpanel.getFlags().getVariantSync("my-feature-flag", fallbackVariant); - -// Use flag variant in your application logic -if ("variant_a".equals(variant.key)) { - showExperimentForVariantA(); -} else if ("variant_b".equals(variant.key)) { - showExperimentForVariantB(); -} else { - showDefaultExperience(); -} -``` - -**Get Flag Value** - -```java -// Get just the flag value synchronously -Object flagValue = mixpanel.getFlags().getVariantValueSync("my-feature-flag", "control"); - -// Use flag value in your application logic -if ("variant_a".equals(flagValue)) { - showExperimentForVariantA(); -} else if ("variant_b".equals(flagValue)) { - showExperimentForVariantB(); -} else { - showDefaultExperience(); -} -``` +This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project *if* the user context is in a rollout group for the feature flag. -**Check if Flag is Enabled** - -```java -// Check if a boolean flag is enabled synchronously -boolean isEnabled = mixpanel.getFlags().isEnabledSync("my-boolean-flag", false); - -if (isEnabled) { - showNewFeature(); -} else { - showOldFeature(); -} -``` - -### Asynchronous Flag Retrieval - -**Get Flag Variant** - -```java -// Get the complete variant object asynchronously -MixpanelFlagVariant fallbackVariant = new MixpanelFlagVariant("control", "control"); -mixpanel.getFlags().getVariant("my-feature-flag", fallbackVariant, new FlagCompletionCallback() { - @Override - public void onComplete(MixpanelFlagVariant variant) { - // This runs on the main thread - if ("variant_a".equals(variant.key)) { - showExperimentForVariantA(); - } else if ("variant_b".equals(variant.key)) { - showExperimentForVariantB(); - } else { - showDefaultExperience(); - } - } -}); -``` +### Asynchronous Flag Variant Retrieval -**Get Flag Value** +**Experiment Flags: Get Variant Value** ```java // Get just the flag value asynchronously @@ -172,9 +103,9 @@ mixpanel.getFlags().getVariantValue("my-feature-flag", "control", new FlagComple @Override public void onComplete(Object value) { // This runs on the main thread - if ("variant_a".equals(value)) { + if (value.equals("variant_a")) { showExperimentForVariantA(); - } else if ("variant_b".equals(value)) { + } else if (value.equals("variant_b")) { showExperimentForVariantB(); } else { showDefaultExperience(); @@ -183,7 +114,7 @@ mixpanel.getFlags().getVariantValue("my-feature-flag", "control", new FlagComple }); ``` -**Check if Flag is Enabled** +**FeatureGates: Check if Flag is Enabled/Disabled** ```java // Check if a boolean flag is enabled asynchronously @@ -200,6 +131,37 @@ mixpanel.getFlags().isEnabled("my-boolean-flag", false, new FlagCompletionCallba }); ``` +### Synchronous Flag Variant Retrieval + +**Experiment Flags: Get Variant Value** + +```java +// Get just the flag value synchronously +Object flagValue = mixpanel.getFlags().getVariantValueSync("my-feature-flag", "control"); + +// Use flag value in your application logic +if (flagValue.equals("variant_a")) { + showExperimentForVariantA(); +} else if (flagValue.equals("variant_b")) { + showExperimentForVariantB(); +} else { + showDefaultExperience(); +} +``` + +**Feature Gates: Check if Flag is Enabled/Disabled** +```java +// Check if a boolean flag is enabled +boolean isEnabled = mixpanel.getFlags().isEnabledSync("my-boolean-flag", false); + +if (isEnabled) { + showNewFeature(); +} else { + showOldFeature(); +} +``` + + ## FAQ / Troubleshooting ### What if I'm not receiving any flags on SDK initialization? @@ -218,54 +180,4 @@ mixpanel.getFlags().isEnabled("my-boolean-flag", false, new FlagCompletionCallba - If using Runtime Targeting, ensure all properties used in targeting are included in the `customProperties` object within `featureFlagsContext` 4. **Check flags readiness**: Use `areFlagsReady()` to check if flags have been loaded before making synchronous calls -5. **Enable debug logging**: Check Android logs for detailed information about flag requests and responses - -### How do I check if flags are ready before making synchronous calls? - -```java -if (mixpanel.getFlags().areFlagsReady()) { - // Safe to make synchronous calls - MixpanelFlagVariant variant = mixpanel.getFlags().getVariantSync("my-flag", fallbackVariant); -} else { - // Use async calls or trigger flag loading - mixpanel.getFlags().loadFlags(); -} -``` - -### What's the difference between synchronous and asynchronous flag methods? - -- **Synchronous methods** (`getVariantSync`, `getVariantValueSync`, `isEnabledSync`): Return immediately with the cached flag value if flags are ready, or the fallback value if flags are not ready. These methods will not trigger a network request and should not be called from the main UI thread if flags might not be ready. -- **Asynchronous methods** (`getVariant`, `getVariantValue`, `isEnabled`): Will trigger a flag fetch if flags are not ready, and call the completion callback with the result once available. The completion callback runs on the main thread. - -### How do I handle flag updates during app lifecycle? - -Flag updates are automatically triggered when: -- You call `identify()` with a new distinct ID -- You manually call `loadFlags()` after updating the context - -For runtime context changes: -```java -JSONObject newContext = new JSONObject(); -newContext.put("company_id", "new_company"); - -// Update context and reload flags -mixpanel.getOptions().featureFlagsContext = newContext; -mixpanel.getFlags().loadFlags(); -``` - -### Thread Safety Considerations - -The Android SDK handles thread safety internally: -- All flag operations are thread-safe -- Synchronous methods can be called from any thread (but avoid calling from main thread if flags might not be ready) -- Asynchronous completion callbacks always run on the main thread -- Flag loading and network requests happen on background threads - -### ProGuard/R8 Configuration - -If you're using code obfuscation, ensure your ProGuard/R8 configuration preserves the necessary classes: - -``` --keep class com.mixpanel.android.mpmetrics.MixpanelFlagVariant { *; } --keep class com.mixpanel.android.mpmetrics.FlagCompletionCallback { *; } -``` \ No newline at end of file +5. **Enable debug logging**: Check Android logs for detailed information about flag requests and responses \ No newline at end of file diff --git a/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx index ac77246768..164871d2b7 100644 --- a/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx +++ b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx @@ -4,7 +4,7 @@ import { Callout } from 'nextra/components' ## Overview -This developer guide will assist you in configuring your web platform for Feature Flags using the [Mixpanel JavaScript SDK](/docs/tracking-methods/sdks/javascript). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. +This developer guide will assist you in configuring your web platform for Feature Flags using the [Mixpanel JavaScript SDK](/docs/tracking-methods/sdks/javascript). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. For complete JavaScript SDK documentation, see the [JavaScript SDK guide](/docs/tracking-methods/sdks/javascript). @@ -89,8 +89,24 @@ mixpanel.flags.update_context({ Lookup the assigned value for a feature flag. This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. -**Example usage** +**Experiment Flags: Get Variant Value** + +```javascript +// Fetch the variant value once flags are ready and track an exposure event *if* the user context is in a rollout group for the feature flag. +const variant_value = await mixpanel.flags.get_variant_value("my-feature-flag", "control"); + +// Use flag value in your application logic +if (variant_value == "variant_a") { + showExperimentForVariantA(); +} else if (variant_value == "variant_b") { + showExperienceForVariantB(); +} else if (variant_value == "control") { + showDefaultExperience(); +} +``` + +**Feature Gates: Check if Flag is Enabled/Disabled** ```javascript // Fetch the variant value once flags are ready and track an exposure event *if* the user context is in a rollout group for the feature flag. const variant_value = await mixpanel.flags.get_variant_value("my-feature-flag", "control"); diff --git a/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx index 4cb100b7f6..6c8a622b01 100644 --- a/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx +++ b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx @@ -4,7 +4,7 @@ import { Callout } from 'nextra/components' ## Overview -This developer guide will assist you in configuring your iOS/macOS platform for Feature Flags using the [Mixpanel Swift SDK](/docs/tracking-methods/sdks/swift). Feature Flags allow you to control feature rollouts, conduct A/B testing, and manage application behavior without deploying new code. +This developer guide will assist you in configuring your iOS/macOS platform for Feature Flags using the [Mixpanel Swift SDK](/docs/tracking-methods/sdks/swift). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. For complete Swift SDK documentation, see the [Swift SDK guide](/docs/tracking-methods/sdks/swift). @@ -12,7 +12,7 @@ For complete Swift SDK documentation, see the [Swift SDK guide](/docs/tracking-m Before implementing Feature Flags, ensure: -- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v4.0.0`](https://github.com/mixpanel/mixpanel-swift/releases/tag/v4.0.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v5.1.3`](https://github.com/mixpanel/mixpanel-swift/releases/tag/v5.1.3)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Initialization @@ -87,76 +87,9 @@ Mixpanel.mainInstance().flags.loadFlags() Lookup the assigned value for a feature flag. This action triggers tracking an exposure event, `$experiment_started` to your Mixpanel project. -### Synchronous Flag Retrieval +### Asynchronous Flag Variant Retrieval -**Get Flag Variant** - -```swift -// Get the complete variant object synchronously -let fallbackVariant = MixpanelFlagVariant(key: "control", value: "control") -let variant = Mixpanel.mainInstance().flags.getVariantSync("my-feature-flag", fallback: fallbackVariant) - -// Use flag variant in your application logic -if variant.key == "variant_a" { - showExperimentForVariantA() -} else if variant.key == "variant_b" { - showExperimentForVariantB() -} else { - showDefaultExperience() -} -``` - -**Get Flag Value** - -```swift -// Get just the flag value synchronously -let flagValue = Mixpanel.mainInstance().flags.getVariantValueSync("my-feature-flag", fallbackValue: "control") - -// Use flag value in your application logic -if flagValue as? String == "variant_a" { - showExperimentForVariantA() -} else if flagValue as? String == "variant_b" { - showExperimentForVariantB() -} else { - showDefaultExperience() -} -``` - -**Check if Flag is Enabled** - -```swift -// Check if a boolean flag is enabled synchronously -let isEnabled = Mixpanel.mainInstance().flags.isEnabledSync("my-boolean-flag", fallbackValue: false) - -if isEnabled { - showNewFeature() -} else { - showOldFeature() -} -``` - -### Asynchronous Flag Retrieval - -**Get Flag Variant** - -```swift -// Get the complete variant object asynchronously -let fallbackVariant = MixpanelFlagVariant(key: "control", value: "control") -Mixpanel.mainInstance().flags.getVariant("my-feature-flag", fallback: fallbackVariant) { variant in - DispatchQueue.main.async { - // Use flag variant in your application logic - if variant.key == "variant_a" { - showExperimentForVariantA() - } else if variant.key == "variant_b" { - showExperimentForVariantB() - } else { - showDefaultExperience() - } - } -} -``` - -**Get Flag Value** +**Experiment Flags: Get Variant Value** ```swift // Get just the flag value asynchronously @@ -177,7 +110,7 @@ Mixpanel.mainInstance().flags.getVariantValue("my-feature-flag", fallbackValue: } ``` -**Check if Flag is Enabled** +**FeatureGates: Check if Flag is Enabled/Disabled** ```swift // Check if a boolean flag is enabled asynchronously @@ -192,6 +125,37 @@ Mixpanel.mainInstance().flags.isEnabled("my-boolean-flag", fallbackValue: false) } ``` +### Synchronous Flag Variant Retrieval + +**Experiment Flags: Get Variant Value** + +```swift +// Get just the flag value synchronously +let flagValue = Mixpanel.mainInstance().flags.getVariantValueSync("my-feature-flag", fallbackValue: "control") + +// Use flag value in your application logic +if flagValue as? String == "variant_a" { + showExperimentForVariantA() +} else if flagValue as? String == "variant_b" { + showExperimentForVariantB() +} else { + showDefaultExperience() +} +``` + +**Feature Gates: Check if Flag is Enabled/Disabled** +```swift +// Check if a boolean flag is enabled +let isEnabled = Mixpanel.mainInstance().flags.isEnabledSync("my-boolean-flag", fallbackValue: false) + +if isEnabled { + showNewFeature() +} else { + showOldFeature() +} +``` + + ## FAQ / Troubleshooting ### What if I'm not receiving any flags on SDK initialization? @@ -210,34 +174,4 @@ Mixpanel.mainInstance().flags.isEnabled("my-boolean-flag", fallbackValue: false) - If using Runtime Targeting, ensure all properties used in targeting are included in the `customProperties` object within `featureFlagsContext` 4. **Check flags readiness**: Use `areFlagsReady()` to check if flags have been loaded before making synchronous calls -5. **Enable debug mode**: Set up logging to see detailed information about flag requests and responses - -### How do I check if flags are ready before making synchronous calls? - -```swift -if Mixpanel.mainInstance().flags.areFlagsReady() { - // Safe to make synchronous calls - let variant = Mixpanel.mainInstance().flags.getVariantSync("my-flag", fallback: fallbackVariant) -} else { - // Use async calls or trigger flag loading - Mixpanel.mainInstance().flags.loadFlags() -} -``` - -### What's the difference between synchronous and asynchronous flag methods? - -- **Synchronous methods** (`getVariantSync`, `getVariantValueSync`, `isEnabledSync`): Return immediately with the cached flag value if flags are ready, or the fallback value if flags are not ready. These methods will not trigger a network request. -- **Asynchronous methods** (`getVariant`, `getVariantValue`, `isEnabled`): Will trigger a flag fetch if flags are not ready, and call the completion handler with the result once available. - -### How do I handle flag updates during app lifecycle? - -Flag updates are automatically triggered when: -- You call `identify()` with a new distinct ID -- You manually call `loadFlags()` after updating the context - -For runtime context changes: -```swift -// Update context and reload flags -Mixpanel.mainInstance().flags.delegate?.getOptions().featureFlagsContext["company_id"] = "new_company" -Mixpanel.mainInstance().flags.loadFlags() -``` \ No newline at end of file +5. **Enable debug mode**: Set up logging to see detailed information about flag requests and responses \ No newline at end of file From 3d1b7cdbfa385a01ea621ef77f1b174a2a461e4a Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 13:03:24 -0700 Subject: [PATCH 03/13] Add beta server side documentation --- .../tracking-methods/sdks/python/_meta.ts | 3 + .../sdks/python/python-flags.mdx | 97 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 pages/docs/tracking-methods/sdks/python/_meta.ts create mode 100644 pages/docs/tracking-methods/sdks/python/python-flags.mdx diff --git a/pages/docs/tracking-methods/sdks/python/_meta.ts b/pages/docs/tracking-methods/sdks/python/_meta.ts new file mode 100644 index 0000000000..2f8a88bad9 --- /dev/null +++ b/pages/docs/tracking-methods/sdks/python/_meta.ts @@ -0,0 +1,3 @@ +export default { + "python-flags": "Feature Flags (Python)", +} diff --git a/pages/docs/tracking-methods/sdks/python/python-flags.mdx b/pages/docs/tracking-methods/sdks/python/python-flags.mdx new file mode 100644 index 0000000000..d006dcd660 --- /dev/null +++ b/pages/docs/tracking-methods/sdks/python/python-flags.mdx @@ -0,0 +1,97 @@ +import { Callout } from 'nextra/components' + +# Implement Feature Flags (Python) + + + The python SDK server-side SDK is currently in Beta. + + +## Overview + +This developer guide will assist you in configuring your server-side Python platform for Feature Flags using the [Mixpanel Python SDK](/docs/tracking-methods/sdks/python). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. + +## Prerequisites + +Before implementing Feature Flags, ensure: + +- You are a Mixpanel ENT customer and have the appropriate version of the SDK installed (minimum supported version is [`v5.0.0b2`](https://github.com/mixpanel/mixpanel-python). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) + +## Flag Evaluation Modes + +There are two modes available for using the python SDK for feature flagging, Local Evaluation and Remote Evaluation. + +For local evaluation, the SDK will poll Mixpanel servers for feature flag configurations. Assignment of user contexts to variants will be done locally within the SDK. This mode is recommended for low latency since there is no network call made at assignment time. + +For remote evaluation, the SDK will make a network call to Mixpanel servers at assignment time. This mode is recommended for use cases where + +## Local Evaluation + + +Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode. + + +- The SDK is configured with a `LocalFlagsConfig` object that specifies parameters: + 1) `api_host` - If you project is in the EU/IN region, this should be set to route to `https://api-eu.mixpanel.com`/`https://api-in.mixpanel.com` respectively. + 2) `enable_polling` - This should be set to `True` to enable local evaluation. + 3) `poll_interval` - This is the interval in seconds at which the SDK will poll Mixpanel servers for feature flag configurations. + +- Polling can be kicked off in two ways + - `start_polling_for_definitions` - This will kick off polling in a background OS thread. + - `astart_polling_for_definitions` - This will kick off polling in an asyncio task. + +- The SDK will continue to poll for the lifetime of the SDK instance or until stopped. + +```python +from mixpanel import Mixpanel + +local_config = mixpanel.LocalFlagsConfig(api_host="https://api.mixpanel.com", enable_polling=True, poll_interval=60) + +mixpanel = Mixpanel("YOUR_PROJECT_TOKEN", local_flags_config=local_config) + +# If enable_polling is set to false, this will fetch definitions only once for the lifetime of the SDK. +mixpanel.local_flags.start_polling_for_definitions() + +# This should be the 'key' of the feature flag from Mixpanel's UX. +flag_key = "sample-flag" + +# This is the fallback variant to return if the user context is not in a rollout group for the flag. +fallback_variant = "control" + +# Current user context for evaluation. +# At minimum, this needs to include the user's distinct_id. +# If any of your feature flags use a Variant Assignment Key other than 'distinct_id', this should also include those keys for evaluation. For example, 'company_id' below +# If any of your feature flags use Runtime targeting, this should also include 'custom_properties' for evaluation +user_context = { + "distinct_id": "1234", + "company_id": "X", + "custom_properties": { + "platform": "python" + } +} + +variant_value = mixpanel.local_flags.get_variant_value(flag_key, fallback_variant, user_context) +``` + +## Remote Evaluation + +- The SDK is configured with a `RemoteFlagsConfig` object to use remote evaluation. + +```python +remote_config = mixpanel.RemoteFlagsConfig(api_host=API_HOST, request_timeout_in_seconds=5) + +mixpanel = mixpanel.Mixpanel(PROJECT_TOKEN, remote_flags_config=remote_config) as mp: + +# get_variant_value usage is the same as for local evaluation, but will make a network call to Mixpanel servers at assignment time. +variant_value = mp.remote_flags.get_variant_value(flag_key, fallback_variant, user_context) + print(f"Variant value: {variant_value}") + +``` + + + + + + + + From bca7015fb9eefaa90050a1ac6d1026cc9bb5c04b Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 14:29:45 -0700 Subject: [PATCH 04/13] Copy over and reformat Neha's documentation --- pages/docs/_meta.tsx | 1 + pages/docs/featureflags.mdx | 209 ++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 pages/docs/featureflags.mdx diff --git a/pages/docs/_meta.tsx b/pages/docs/_meta.tsx index d4de939167..c7be37d072 100644 --- a/pages/docs/_meta.tsx +++ b/pages/docs/_meta.tsx @@ -43,6 +43,7 @@ export default { }, reports: "Reports", boards: "Boards", + featureflags: "Feature Flags", experiments: "Experiments", metric_tree: "Metric Trees", users: "Users", diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx new file mode 100644 index 0000000000..4d0473bf96 --- /dev/null +++ b/pages/docs/featureflags.mdx @@ -0,0 +1,209 @@ +import { Cards, Callout } from 'nextra/components' + +# Feature Flags + + +Feature flags will be coming soon for ENT customers. + + +## Overview + +**Feature Flags** let you control who sees a feature and when. Use them to: + +- **Gradually roll out** changes (E.g 1% → 10% → 100%) +- **Target** cohorts, regions, platforms, or group accounts +- **Kill-switch** risky functionality instantly +- **Serve variants** for A/B/x tests and analyze results with **Mixpanel Experiments** + +**Flags** deliver variants to users whereas **Experiments** measure impact with statistical rigor. Use flags to deploy and orchestrate and use experiments to decide. + +## Concepts & terminology + +- **Flag Key** — unique identifier for a flag used by SDKs. +- **Variant Assignment Key** — the randomization bucket unit: `distinct_id` (user), `device_id`, or a **group key** like `account_id`. +- **Variants** — experience labels (e.g., `control`, `A`, `B`). +- **Variant Splits** — allocation across variants (e.g., 90%/10%). +- **Fallback Value** — variant to use when an assignment is unavailable. +- **Sticky Variants** — the same entity keeps the same variant over time. +- **Rollout Groups** - The configuration determining which users are in the rollout. This is comprised of: + - **Targeting** — eligibility definition (All Users vs Cohorts; may include runtime properties). + - **Rollout %** — percentage of the eligible audience that receives the flag now. +- **Rollout %** — percentage of the eligible Rollout Group that receives the flag now. +- **Runtime Properties** — request-time attributes (e.g., URL path, app version) used to target immediately. +- **Assignment vs Exposure** — assignment is deciding the variant; exposure is when your app **uses** that variant to render. +- **Feature Flag API Request** - is a call made to a feature flag API to retrieve the current state or configuration of one or more feature flags. This request allows an application to dynamically determine which features should be active for a particular user + +## Types of Feature Flags + +We support the following types of Flags + +1. **Feature Gate** : Toggle a feature on or off for targeted users or all users. Useful for phased or controlled rollouts. +2. **Experiment :** Deliver different variant experiences (e.g., layouts, flows, pricing) to a targeted group of users. Enables measuring and analyzing impact. +3. [Coming Soon] **Dynamic Config** : Configure features with flexible key-value pairs instead of just on/off. Lets you: + - Pass JSON payloads (e.g., `{"cta_text": "Buy now", "discount": 20}`) to customize behavior or UI dynamically + - Update values instantly without redeploying code + +## Variant Assignment Key + +This is the randomization bucket unit: `distinct_id` (user), `device_id`, or a **group key** like `account_id`. + +**How to choose the right key?** + +- **User** `distinct_id` — best for logged-in experiences across device; a user sees a consistent experience across various sessions and devices +- **Device** `device_id` — best for pre-auth or acquisition flows; a device keeps a consistent variant between pre-auth and post-auth experiences. + +- For projects that support ([Group Analytics](/docs/data-structure/group-analytics)), you can choose one of your group keys as the Variant Assignment Key as well. + - **Group** `group_id` — target by account/org using a group key (e.g., `account_id`). + +## Variants Management + +Variants are served / allocated around the `variant assignment key` + +Variant management includes 3 concepts - + +- Variants are the experiences to serve. (e.g., `control`, `A`, `B`). +- Variant split % is the allocation across the variants. + - For example, 10% of users in variant A, and 90% in variant B. +- Sticky Variants ensures continuity in the variant experience served + - If a user is assigned to a sticky variant B, regardless of how variant splits, rollout percentagek, or cohort memberships change in the future, the user will continue to see the variant B. + + +Control variant by is always set to non-sticky. +This is to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. + + +## Rollout Groups + +Feature flags may consistent of one or more rollout groups. Users are evaluated against each rollout group in order until one is found that the user qualitifes for. +They consist of two parts. + 1) Cohorts + 2) Rollout Percentage + +### Cohorts + +You can optionally target rollout of your feature flags to subsets of your user base rather than to all your users with [Cohorts](https://docs.mixpanel.com/docs/cohorts). +These are dynamic audiences of Mixpanel users based on user behavior or properties. Use these to target feature flag rollouts to specific subsets of your user base. + + + Cohorts used in feature flag targeting refresh on a periodic cadence (~every 2 hours). So once a user qualitifes for a cohort, it can take up to 2 hours before they see a desired experience. + If you want users to continue seeing the same variant even if they disqualify from the cohort in the future, couple this with **Sticky Variants.** This will ensure a user continues to see the new experience untill he flag is turned off. + + +The configuration determining which users are in the rollout. + +- **Runtime Targeting** + - When building a cohort, if you add a filter, navgiate to `+ Create New`, you'll be able to add a new runtime property filter. + - Runtime properties (e.g., `platform`, `path`, `country`) should be passed by the SDK at request time for immediate, per-request decisions. + +### Rollout Percentage + +This is the percentage of the requests that should be targeted, according to the Variant Assignment Key. + +Example: If we want to rollout to 50% of Active Users cohort, and 10% to Dormant User Cohort, we would create + +- 2 rollout groups : Rollout Group 1 - Active Users, Rollout Group 2 - Dormant Users +- Rollout percentage will be applied to each Rollout Group : 50% and 10% respectively + +Variant allocation happens within the roll-out group. + +Example: Building on the same example above, variant allocation is 50-50 for A/B. + +- Rollout Group 1 - Active users will see - 25% users in A (50% of 50%); 5% users in B (50% of 50%) +- Rollout Group 2 - Dormant users will see - 5% users in A (50% of 10%); 5% users in B (50% of 10%) + +## Implementation + +Feature Flagging is supported on three client-side SDK's: Web, iOS, and Android and currently on one server-side SDK, python. + +See our developer guides on implementing feature flags on these platforms below: + + + + + + + + +Coming soon: React Native, Java, Ruby + + +If you have any other SDK requests, please reach out to the support team to let us know. + + +## **Frequently Asked Questions** + +- **How do [Data Views](/docs/data-governance/data-views-and-classification),affect feature flags? + - Feature flags are scoped to data views. + - If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. + - Only users with access to a data-view and can view and edit the flag + +- **Can I target a cohort, but also include run-time targeting like device or url path?** + Yes, you can. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. + +- **Why is control variant always non-sticky? I want all my variants to be sticky** + Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. + NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants + This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants + +- **Are there any limits to variants or rollout group?** + Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag + +- **How do we avoid overlapping target audiences across 2 different feature flags?** + Let's say we have 2 features: feature A and feature B, and we want these to be non-overlapping in audience targeting. + In the feature flag B page, in target audience - + - Create Rollout Group 1: any user who was exposed to feature flag A + - Variant served: control 100% (no new experience, revert to default) + - Rollout Percentage : 100% + - Create Rollout Group 2: All users, or any specific users you want for flag B + +- **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** + When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. + This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event + + +### QA Testers + +This section allows you to override which variants specific users who will receive the experience. + +## Governance, approvals & audit + +We recommend establish light-weight controls without slowing teams: + +- **Ownership** — Every flag must have an owner and an expiry/intent note (release / experiment / kill-switch). +- **Change management** — Use a review process for potentially risky changes, such as those impacting revenue flows or have widespread impact. +- **Auditability** — Use the Feature Flag audit history to review changes that are made to a flag over time. + +## Performance, Reliability & security +- **Privacy** — send only the context/runtime properties you need; avoid sensitive PII. +- **Regions** — keep traffic within region by using the correct project & API hosts. + - EU & IN projects must initialize SDK's with the correct api host endpoints for their region. +- **Choose the best mode for your use case** + - **Remote evaluation** + - This is supported by client SDK's. + - Supports mixpanel cohorts targeting & sticky variants. + - Each evaluation sends a network request so handle timeouts and network failures appropriately with + - **Local evaluation** + - In addition, server-side SDK's support this mode, where flag settings are periodically polled. + - Each evaluation does not require a network request so is low latency and not expected to throw errors. + +### **Frequently Asked Questions** + +- **How do [Data Views](/docs/data-governance/data-views-and-classification),affect feature flags? + - Feature flags are scoped to data views. + - If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. + - Only users with access to a data-view and can view and edit the flag + +- **Can I target a cohort, but also include run-time targeting like device or url path?** + Yes, you can. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. + +- **Why is control variant always non-sticky? I want all my variants to be sticky** + Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. + NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants + This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants + +- **Are there any limits to variants or rollout group?** + Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag + +- **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** + When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. + This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event From 623e9e84048050423b7ec4902747bed2d6e8d4e5 Mon Sep 17 00:00:00 2001 From: Myron Fung Date: Mon, 29 Sep 2025 14:41:22 -0700 Subject: [PATCH 05/13] remove duplicate FAQ section --- pages/docs/featureflags.mdx | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 4d0473bf96..52d5e9d33f 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -130,37 +130,6 @@ Coming soon: React Native, Java, Ruby If you have any other SDK requests, please reach out to the support team to let us know. -## **Frequently Asked Questions** - -- **How do [Data Views](/docs/data-governance/data-views-and-classification),affect feature flags? - - Feature flags are scoped to data views. - - If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. - - Only users with access to a data-view and can view and edit the flag - -- **Can I target a cohort, but also include run-time targeting like device or url path?** - Yes, you can. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. - -- **Why is control variant always non-sticky? I want all my variants to be sticky** - Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. - NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants - This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants - -- **Are there any limits to variants or rollout group?** - Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag - -- **How do we avoid overlapping target audiences across 2 different feature flags?** - Let's say we have 2 features: feature A and feature B, and we want these to be non-overlapping in audience targeting. - In the feature flag B page, in target audience - - - Create Rollout Group 1: any user who was exposed to feature flag A - - Variant served: control 100% (no new experience, revert to default) - - Rollout Percentage : 100% - - Create Rollout Group 2: All users, or any specific users you want for flag B - -- **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** - When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. - This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event - - ### QA Testers This section allows you to override which variants specific users who will receive the experience. @@ -188,7 +157,7 @@ We recommend establish light-weight controls without slowing teams: ### **Frequently Asked Questions** -- **How do [Data Views](/docs/data-governance/data-views-and-classification),affect feature flags? +- **How do [Data Views](/docs/data-governance/data-views-and-classification) affect feature flags?** - Feature flags are scoped to data views. - If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. - Only users with access to a data-view and can view and edit the flag From c3343395dd8f6a421387a9791d4b848ab6e44f8d Mon Sep 17 00:00:00 2001 From: Myron Fung Date: Mon, 29 Sep 2025 14:53:07 -0700 Subject: [PATCH 06/13] edits to featureflags page --- pages/docs/featureflags.mdx | 41 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 52d5e9d33f..5d904f0c1c 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -3,7 +3,7 @@ import { Cards, Callout } from 'nextra/components' # Feature Flags -Feature flags will be coming soon for ENT customers. + Feature Flags is coming soon for customers with an Enterprise subscription plan. ## Overview @@ -68,8 +68,7 @@ Variant management includes 3 concepts - - If a user is assigned to a sticky variant B, regardless of how variant splits, rollout percentagek, or cohort memberships change in the future, the user will continue to see the variant B. -Control variant by is always set to non-sticky. -This is to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. +Control variant by is always set to non-sticky. This is to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. ## Rollout Groups @@ -127,7 +126,7 @@ See our developer guides on implementing feature flags on these platforms below: Coming soon: React Native, Java, Ruby -If you have any other SDK requests, please reach out to the support team to let us know. +If you'd like to see Feature Flags availability in other SDKs, please [reach out to the Support team](https://mixpanel.com/get-support). ### QA Testers @@ -157,22 +156,26 @@ We recommend establish light-weight controls without slowing teams: ### **Frequently Asked Questions** -- **How do [Data Views](/docs/data-governance/data-views-and-classification) affect feature flags?** - - Feature flags are scoped to data views. - - If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. - - Only users with access to a data-view and can view and edit the flag +**How do [Data Views](/docs/data-governance/data-views-and-classification) affect feature flags?** -- **Can I target a cohort, but also include run-time targeting like device or url path?** - Yes, you can. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. +Feature flags are scoped to data views. If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. Only users with access to a data-view and can view and edit the flag -- **Why is control variant always non-sticky? I want all my variants to be sticky** - Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. - NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants - This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants +**Can I target a cohort, but also include run-time targeting like device or url path?** -- **Are there any limits to variants or rollout group?** - Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag +Yes. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. -- **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** - When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. - This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event +**Why is control variant always non-sticky? I want all my variants to be sticky** + +Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. + +NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants. This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants + +**Are there any limits to variants or rollout group?** + +Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag + +**We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** + +When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. + +This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event From ef7aebe37d3d06d7b92e6e9b77bc8a063dbc6a51 Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 14:54:34 -0700 Subject: [PATCH 07/13] spell fixes --- pages/docs/featureflags.mdx | 14 +++++++------- .../tracking-methods/sdks/python/python-flags.mdx | 4 ---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 5d904f0c1c..c5863954fa 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -37,7 +37,7 @@ import { Cards, Callout } from 'nextra/components' We support the following types of Flags -1. **Feature Gate** : Toggle a feature on or off for targeted users or all users. Useful for phased or controlled rollouts. +1. **Feature Gate** : Toggle a feature on or off for targeted users or all users. Useful for phased or controlled rollout. 2. **Experiment :** Deliver different variant experiences (e.g., layouts, flows, pricing) to a targeted group of users. Enables measuring and analyzing impact. 3. [Coming Soon] **Dynamic Config** : Configure features with flexible key-value pairs instead of just on/off. Lets you: - Pass JSON payloads (e.g., `{"cta_text": "Buy now", "discount": 20}`) to customize behavior or UI dynamically @@ -65,7 +65,7 @@ Variant management includes 3 concepts - - Variant split % is the allocation across the variants. - For example, 10% of users in variant A, and 90% in variant B. - Sticky Variants ensures continuity in the variant experience served - - If a user is assigned to a sticky variant B, regardless of how variant splits, rollout percentagek, or cohort memberships change in the future, the user will continue to see the variant B. + - If a user is assigned to a sticky variant B, regardless of how variant splits, rollout percentage, or cohort memberships change in the future, the user will continue to see the variant B. Control variant by is always set to non-sticky. This is to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. @@ -73,7 +73,7 @@ Control variant by is always set to non-sticky. This is to ensure this is the on ## Rollout Groups -Feature flags may consistent of one or more rollout groups. Users are evaluated against each rollout group in order until one is found that the user qualitifes for. +Feature flags may consistent of one or more rollout groups. Users are evaluated against each rollout group in order until one is found that the user qualifies for. They consist of two parts. 1) Cohorts 2) Rollout Percentage @@ -81,17 +81,17 @@ They consist of two parts. ### Cohorts You can optionally target rollout of your feature flags to subsets of your user base rather than to all your users with [Cohorts](https://docs.mixpanel.com/docs/cohorts). -These are dynamic audiences of Mixpanel users based on user behavior or properties. Use these to target feature flag rollouts to specific subsets of your user base. +These are dynamic audiences of Mixpanel users based on user behavior or properties. Use these to target feature flags to specific subsets of your user base. - Cohorts used in feature flag targeting refresh on a periodic cadence (~every 2 hours). So once a user qualitifes for a cohort, it can take up to 2 hours before they see a desired experience. - If you want users to continue seeing the same variant even if they disqualify from the cohort in the future, couple this with **Sticky Variants.** This will ensure a user continues to see the new experience untill he flag is turned off. + Cohorts used in feature flag targeting refresh on a periodic cadence (~every 2 hours). So once a user qualifies for a cohort, it can take up to 2 hours before they see a desired experience. + If you want users to continue seeing the same variant even if they disqualify from the cohort in the future, couple this with **Sticky Variants.** This will ensure a user continues to see the new experience until he flag is turned off. The configuration determining which users are in the rollout. - **Runtime Targeting** - - When building a cohort, if you add a filter, navgiate to `+ Create New`, you'll be able to add a new runtime property filter. + - When building a cohort, if you add a filter, navigate to `+ Create New`, you'll be able to add a new runtime property filter. - Runtime properties (e.g., `platform`, `path`, `country`) should be passed by the SDK at request time for immediate, per-request decisions. ### Rollout Percentage diff --git a/pages/docs/tracking-methods/sdks/python/python-flags.mdx b/pages/docs/tracking-methods/sdks/python/python-flags.mdx index d006dcd660..c56b38fab5 100644 --- a/pages/docs/tracking-methods/sdks/python/python-flags.mdx +++ b/pages/docs/tracking-methods/sdks/python/python-flags.mdx @@ -36,10 +36,6 @@ Targeting by Mixpanel cohorts and sticky variants are not supported in Local Eva 2) `enable_polling` - This should be set to `True` to enable local evaluation. 3) `poll_interval` - This is the interval in seconds at which the SDK will poll Mixpanel servers for feature flag configurations. -- Polling can be kicked off in two ways - - `start_polling_for_definitions` - This will kick off polling in a background OS thread. - - `astart_polling_for_definitions` - This will kick off polling in an asyncio task. - - The SDK will continue to poll for the lifetime of the SDK instance or until stopped. ```python From 870cf46e95ff9d9e8e767f56c244238f376ab0cd Mon Sep 17 00:00:00 2001 From: Myron Fung Date: Mon, 29 Sep 2025 15:09:40 -0700 Subject: [PATCH 08/13] minor edits --- pages/docs/featureflags.mdx | 2 +- .../docs/tracking-methods/sdks/android/android-flags.mdx | 8 ++++---- .../sdks/javascript/javascript-flags.mdx | 9 +++++---- pages/docs/tracking-methods/sdks/python/python-flags.mdx | 8 ++++---- pages/docs/tracking-methods/sdks/swift/swift-flags.mdx | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index c5863954fa..97669c2e7c 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -154,7 +154,7 @@ We recommend establish light-weight controls without slowing teams: - In addition, server-side SDK's support this mode, where flag settings are periodically polled. - Each evaluation does not require a network request so is low latency and not expected to throw errors. -### **Frequently Asked Questions** +### Frequently Asked Questions **How do [Data Views](/docs/data-governance/data-views-and-classification) affect feature flags?** diff --git a/pages/docs/tracking-methods/sdks/android/android-flags.mdx b/pages/docs/tracking-methods/sdks/android/android-flags.mdx index c431477915..52b65bd99e 100644 --- a/pages/docs/tracking-methods/sdks/android/android-flags.mdx +++ b/pages/docs/tracking-methods/sdks/android/android-flags.mdx @@ -12,7 +12,7 @@ For complete Android SDK documentation, see the [Android SDK guide](/docs/tracki Before implementing Feature Flags, ensure: -- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v8.2.4`](https://github.com/mixpanel/mixpanel-android/releases/tag/v8.2.4)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are on an Enterprise subscription plan and have the latest version of the SDK installed (minimum supported version is [`v8.2.4`](https://github.com/mixpanel/mixpanel-android/releases/tag/v8.2.4)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Initialization @@ -24,7 +24,7 @@ The response will include an assigned variant for each flag that the user contex **Example Usage** -```java +```java Java MixpanelOptions options = new MixpanelOptions(); options.featureFlagsEnabled = true; @@ -35,7 +35,7 @@ If your flag is configured with a Variant Assignment Key other than `distinct_id For example, for a Variant Assignment Key, `company_id`, you would setup the SDK as follows: -```java +```java Java JSONObject context = new JSONObject(); context.put("company_id", "X"); @@ -162,7 +162,7 @@ if (isEnabled) { ``` -## FAQ / Troubleshooting +## Frequently Asked Questions ### What if I'm not receiving any flags on SDK initialization? diff --git a/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx index 164871d2b7..02802d18ab 100644 --- a/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx +++ b/pages/docs/tracking-methods/sdks/javascript/javascript-flags.mdx @@ -12,19 +12,20 @@ For complete JavaScript SDK documentation, see the [JavaScript SDK guide](/docs/ Before implementing Feature Flags, ensure: -- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v2.70.0`](https://github.com/mixpanel/mixpanel-js/releases/tag/v2.70.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are on an Enterprise subscription plan and have the latest version of the SDK installed (minimum supported version is [`v2.70.0`](https://github.com/mixpanel/mixpanel-js/releases/tag/v2.70.0)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Initialization Initializing the SDK with the `flags` option enables making an outbound request to Mixpanel servers with the current user context. + The server will assign the user context to a variant for each feature flag according to the how they are configured in the Mixpanel UX. The response will include an assigned variant for each flag that the user context is in a rollout group for. If a flag is not returned, it most likely signifies that the user was either not in the rollout percentage for a flag or in the configured targeting cohort. **Example Usage** -```javascript +```javascript Javascript mixpanel.init("YOUR_PROJECT_TOKEN", { debug: true, flags: true, @@ -35,7 +36,7 @@ If your flag is configured with a Variant Assignment Key other than `distinct_id For example, for a Variant Assignment Key, `company_id`, you would setup the SDK as follows. -```javascript +```javascript Javascript mixpanel.init("YOUR_PROJECT_TOKEN", { debug: true, flags: { @@ -121,7 +122,7 @@ if (variant_value == "variant_a") { } ``` -## FAQ / Troubleshooting +## Frequently Asked Questions ### What if I'm not receiving any flags on SDK initialization? diff --git a/pages/docs/tracking-methods/sdks/python/python-flags.mdx b/pages/docs/tracking-methods/sdks/python/python-flags.mdx index c56b38fab5..1450d2f381 100644 --- a/pages/docs/tracking-methods/sdks/python/python-flags.mdx +++ b/pages/docs/tracking-methods/sdks/python/python-flags.mdx @@ -3,18 +3,18 @@ import { Callout } from 'nextra/components' # Implement Feature Flags (Python) - The python SDK server-side SDK is currently in Beta. + The Python server-side SDK is currently in Beta. ## Overview -This developer guide will assist you in configuring your server-side Python platform for Feature Flags using the [Mixpanel Python SDK](/docs/tracking-methods/sdks/python). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. +This developer guide will assist you in configuring your server-side Python platform for [Feature Flags](/docs/featureflags) using the [Mixpanel Python SDK](/docs/tracking-methods/sdks/python). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code. ## Prerequisites -Before implementing Feature Flags, ensure: +Before implementing [Feature Flags](/docs/featureflags), ensure: -- You are a Mixpanel ENT customer and have the appropriate version of the SDK installed (minimum supported version is [`v5.0.0b2`](https://github.com/mixpanel/mixpanel-python). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are on an Enterprise subscription plan and have the appropriate version of the SDK installed (minimum supported version is [`v5.0.0b2`](https://github.com/mixpanel/mixpanel-python). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Evaluation Modes diff --git a/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx index 6c8a622b01..c4e50150fa 100644 --- a/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx +++ b/pages/docs/tracking-methods/sdks/swift/swift-flags.mdx @@ -12,7 +12,7 @@ For complete Swift SDK documentation, see the [Swift SDK guide](/docs/tracking-m Before implementing Feature Flags, ensure: -- You are a Mixpanel ENT customer and have the latest version of the SDK installed (minimum supported version is [`v5.1.3`](https://github.com/mixpanel/mixpanel-swift/releases/tag/v5.1.3)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. +- You are on an Enterprise subscription plan and have the latest version of the SDK installed (minimum supported version is [`v5.1.3`](https://github.com/mixpanel/mixpanel-swift/releases/tag/v5.1.3)). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK. - You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens) ## Flag Initialization @@ -156,7 +156,7 @@ if isEnabled { ``` -## FAQ / Troubleshooting +## Frequently Asked Questions ### What if I'm not receiving any flags on SDK initialization? From 26e265d8c9fb6db399fdaa4c1e0303ad1eed57bd Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 15:10:47 -0700 Subject: [PATCH 09/13] fixing trailing line --- pages/docs/tracking-methods/sdks/python/python-flags.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/tracking-methods/sdks/python/python-flags.mdx b/pages/docs/tracking-methods/sdks/python/python-flags.mdx index 1450d2f381..beb39a0d40 100644 --- a/pages/docs/tracking-methods/sdks/python/python-flags.mdx +++ b/pages/docs/tracking-methods/sdks/python/python-flags.mdx @@ -23,7 +23,7 @@ There are two modes available for using the python SDK for feature flagging, Loc For local evaluation, the SDK will poll Mixpanel servers for feature flag configurations. Assignment of user contexts to variants will be done locally within the SDK. This mode is recommended for low latency since there is no network call made at assignment time. -For remote evaluation, the SDK will make a network call to Mixpanel servers at assignment time. This mode is recommended for use cases where +For remote evaluation, the SDK will make a network call to Mixpanel servers at assignment time. This mode is recommended for use cases where you want to leverage Mixpanel cohorts for user targeting or sticky variants for persistent variant assignments. ## Local Evaluation From abb9d987d369ccb678abb3469b6c51499d22ea5e Mon Sep 17 00:00:00 2001 From: Neha Nathan <93923710+nsquare92@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:53:19 -0700 Subject: [PATCH 10/13] Neha edits Added some items that were left out --- pages/docs/featureflags.mdx | 112 +++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 97669c2e7c..28a6526032 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -36,31 +36,30 @@ import { Cards, Callout } from 'nextra/components' ## Types of Feature Flags We support the following types of Flags - 1. **Feature Gate** : Toggle a feature on or off for targeted users or all users. Useful for phased or controlled rollout. 2. **Experiment :** Deliver different variant experiences (e.g., layouts, flows, pricing) to a targeted group of users. Enables measuring and analyzing impact. 3. [Coming Soon] **Dynamic Config** : Configure features with flexible key-value pairs instead of just on/off. Lets you: - Pass JSON payloads (e.g., `{"cta_text": "Buy now", "discount": 20}`) to customize behavior or UI dynamically - Update values instantly without redeploying code -## Variant Assignment Key +## Targeting & Identity Management + +### Variant Assignment Key This is the randomization bucket unit: `distinct_id` (user), `device_id`, or a **group key** like `account_id`. **How to choose the right key?** - - **User** `distinct_id` — best for logged-in experiences across device; a user sees a consistent experience across various sessions and devices - **Device** `device_id` — best for pre-auth or acquisition flows; a device keeps a consistent variant between pre-auth and post-auth experiences. - For projects that support ([Group Analytics](/docs/data-structure/group-analytics)), you can choose one of your group keys as the Variant Assignment Key as well. - **Group** `group_id` — target by account/org using a group key (e.g., `account_id`). -## Variants Management +### Variants Management Variants are served / allocated around the `variant assignment key` Variant management includes 3 concepts - - - Variants are the experiences to serve. (e.g., `control`, `A`, `B`). - Variant split % is the allocation across the variants. - For example, 10% of users in variant A, and 90% in variant B. @@ -71,45 +70,74 @@ Variant management includes 3 concepts - Control variant by is always set to non-sticky. This is to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. -## Rollout Groups +### Rollout Groups Feature flags may consistent of one or more rollout groups. Users are evaluated against each rollout group in order until one is found that the user qualifies for. -They consist of two parts. - 1) Cohorts - 2) Rollout Percentage - -### Cohorts -You can optionally target rollout of your feature flags to subsets of your user base rather than to all your users with [Cohorts](https://docs.mixpanel.com/docs/cohorts). -These are dynamic audiences of Mixpanel users based on user behavior or properties. Use these to target feature flags to specific subsets of your user base. +You can target 'All Users', or optionally target rollout of your feature flags to subsets of your user base rather than to all your users with [Cohorts](https://docs.mixpanel.com/docs/cohorts). +These are dynamic audiences of Mixpanel users based on user behavior or properties. Use these to target feature flags to specific subsets of your user base. For example, target only users who did 5 purchases in the last week. Cohorts used in feature flag targeting refresh on a periodic cadence (~every 2 hours). So once a user qualifies for a cohort, it can take up to 2 hours before they see a desired experience. If you want users to continue seeing the same variant even if they disqualify from the cohort in the future, couple this with **Sticky Variants.** This will ensure a user continues to see the new experience until he flag is turned off. -The configuration determining which users are in the rollout. - -- **Runtime Targeting** - - When building a cohort, if you add a filter, navigate to `+ Create New`, you'll be able to add a new runtime property filter. - - Runtime properties (e.g., `platform`, `path`, `country`) should be passed by the SDK at request time for immediate, per-request decisions. +**Runtime Targeting** enabled targeting users immediately based on device or platform properties. For example, only users who are on android device and in the UK +- When building a cohort, if you add a filter, navigate to `+ Create New`, you'll be able to add a new runtime property filter. +- Runtime properties (e.g., `platform`, `path`, `country`) should be passed by the SDK at request time for immediate, per-request decisions. ### Rollout Percentage This is the percentage of the requests that should be targeted, according to the Variant Assignment Key. Example: If we want to rollout to 50% of Active Users cohort, and 10% to Dormant User Cohort, we would create - - 2 rollout groups : Rollout Group 1 - Active Users, Rollout Group 2 - Dormant Users - Rollout percentage will be applied to each Rollout Group : 50% and 10% respectively Variant allocation happens within the roll-out group. Example: Building on the same example above, variant allocation is 50-50 for A/B. - - Rollout Group 1 - Active users will see - 25% users in A (50% of 50%); 5% users in B (50% of 50%) - Rollout Group 2 - Dormant users will see - 5% users in A (50% of 10%); 5% users in B (50% of 10%) + +## Governance, permissions & audit trail + +We recommend establish light-weight controls without slowing teams: +- **Project Role** — you need to have at least an “analyst” role to create and edit feature flags. “Consumer” roles can only view feature flags. + [coming soon] Overall Feature Flag permissions - this setting allows you to give users or teams access to all feature flags. It overrides the permisions set at a per-flag level. For example, you might want your ops-lead team to have edit access to all flags for emergencies. +- **Feature Flag Permissions** — You can manage share settings per flag.. Only editors for a flag will have access to modify a flag generally. +- **Audit Trail** — Shows the history of changes related to the flag. This allows you to know the change history (who, what, when) of all the updates. + +### QA Testers + +This section allows you to whitelist users who will receive the experience, vs rolling out more broadly. You can select users based on the $email user profile property. Once selected, you can specify which experience you would like each user to get. + +### Testing Environment + +Use separate Mixpanel projects, which are connected to your different environments, to reduce risk and promote safety. You might have just 1 or 2 of these, which is also fine - +1. **Dev** **Project** — rapid iteration; permissive targeting +2. **Staging Project** — mirrors prod cohorts; dry runs for promotion. +3. **Prod Project** — customer-facing + +Recommended workflow: +- Create the flag in **dev** with a consistent **Flag Key**. Validate eligibility, variants, etc. +- Create the same flag in **staging.** Use the same **Flag Key.** QA Test in this mode +- Lastly, create the same flag in **prod.** Use the same **Flag Key.** Ensure the right edit permissions are provided, and the right rollout % is set. + + +## Performance, Reliability & security + +- **Privacy** — + - EU & IN projects must initialize the SDK’s with the correct api host endpoints for their regions. + - You should only send the context/runtime properties you need; avoid sensitive PII. +- **Regions** — keep traffic within region by using the correct project & API hosts. +- **Reliability** — Mixpanel analytics downtime will result in suspended cohort membership refreshes, though feature flag variants will continue to be served. + - When using sticky variants, the last available variant per user will be served. + - In case of Feature flagging service downtime, your fallback variant will be served by the SDKs. +- **Performance** - The latency of Feature flags API responses is usually on the order of milliseconds. + - Cohort membership is refreshed every 2 hours when targeting anything aside from 'All Users' or 'Run Time Properties'. Therefore, new users entering cohorts may not be reflected in Feature flags API responses for up to that 2 hour period. + ## Implementation Feature Flagging is supported on three client-side SDK's: Web, iOS, and Android and currently on one server-side SDK, python. @@ -129,53 +157,29 @@ Coming soon: React Native, Java, Ruby If you'd like to see Feature Flags availability in other SDKs, please [reach out to the Support team](https://mixpanel.com/get-support). -### QA Testers - -This section allows you to override which variants specific users who will receive the experience. - -## Governance, approvals & audit - -We recommend establish light-weight controls without slowing teams: - -- **Ownership** — Every flag must have an owner and an expiry/intent note (release / experiment / kill-switch). -- **Change management** — Use a review process for potentially risky changes, such as those impacting revenue flows or have widespread impact. -- **Auditability** — Use the Feature Flag audit history to review changes that are made to a flag over time. - -## Performance, Reliability & security -- **Privacy** — send only the context/runtime properties you need; avoid sensitive PII. -- **Regions** — keep traffic within region by using the correct project & API hosts. - - EU & IN projects must initialize SDK's with the correct api host endpoints for their region. -- **Choose the best mode for your use case** - - **Remote evaluation** - - This is supported by client SDK's. - - Supports mixpanel cohorts targeting & sticky variants. - - Each evaluation sends a network request so handle timeouts and network failures appropriately with - - **Local evaluation** - - In addition, server-side SDK's support this mode, where flag settings are periodically polled. - - Each evaluation does not require a network request so is low latency and not expected to throw errors. - -### Frequently Asked Questions +## Frequently Asked Questions **How do [Data Views](/docs/data-governance/data-views-and-classification) affect feature flags?** - Feature flags are scoped to data views. If targeting your flag to specific user cohorts, only end users included in the data view where the flag is created, will be targeted. Only users with access to a data-view and can view and edit the flag **Can I target a cohort, but also include run-time targeting like device or url path?** - Yes. You can couple run-time targeting with general cohorts. It works with an and condition across the 2 groups. **Why is control variant always non-sticky? I want all my variants to be sticky** - -Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. - +Control variant is set to always be non-sticky to ensure this is the only group of users that can move up to other variants if allocation of other variants is increased. This is to avoid users moving from non-control variants. NOTE: If you do want all users to be sticky and do not anticipate needing to change the variant allocation, mark control variant as 0%, and allocate all the 100% to the other variants. This is recommended for use-cases where you have no default or control experience, and are testing a brand new experience with 2+ variants +**How do we avoid overlapping target audiences across 2 different feature flags?** +Let’s say we have 2 features: feature A and feature B, and we want these to be non-overlapping in audience targeting. +In the feature flag B page, in the target audience - +- Create Rollout Group 1: any user who was exposed to feature flag A + - Variant served: control 100% (no new experience, revert to default) + - Rollout % : 100% +- Create Rollout Group 2: All users, or any specific users you want for flag B + **Are there any limits to variants or rollout group?** - Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** - When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. - This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event From 47161c78b8deb63b42eba41a5e72260c21e5f746 Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 15:56:17 -0700 Subject: [PATCH 11/13] Fixing mispelling --- pages/docs/featureflags.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 28a6526032..72fec0ef73 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -105,7 +105,7 @@ Example: Building on the same example above, variant allocation is 50-50 for A/B We recommend establish light-weight controls without slowing teams: - **Project Role** — you need to have at least an “analyst” role to create and edit feature flags. “Consumer” roles can only view feature flags. - [coming soon] Overall Feature Flag permissions - this setting allows you to give users or teams access to all feature flags. It overrides the permisions set at a per-flag level. For example, you might want your ops-lead team to have edit access to all flags for emergencies. + [coming soon] Overall Feature Flag permissions - this setting allows you to give users or teams access to all feature flags. It overrides the permissions set at a per-flag level. For example, you might want your ops-lead team to have edit access to all flags for emergencies. - **Feature Flag Permissions** — You can manage share settings per flag.. Only editors for a flag will have access to modify a flag generally. - **Audit Trail** — Shows the history of changes related to the flag. This allows you to know the change history (who, what, when) of all the updates. From 31a514edd222b66f0eb9580c71439990783220d4 Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 16:05:42 -0700 Subject: [PATCH 12/13] Fix formatting due to '$' usage --- pages/docs/featureflags.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 72fec0ef73..7dd864774b 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -181,5 +181,5 @@ In the feature flag B page, in the target audience - Yes, today you can have a maximum of 5 variants per flag, and a maximum of 5 rollout groups per flag **We use a CDP in our company. How do we use Mixpanel Feature Flags with our CDP?** -When you initialize the mixpanel feature flag SDK, configure it to not track any $experiment_started events directly to Mixpanel. +When you initialize the mixpanel feature flag SDK, configure it to not track any `$experiment_started` events directly to Mixpanel. This way you use the mixpanel SDK to serve the feature flags, but when an end-user sees exposure, they manually use their existing method of tracking events through their CDP to mixpanel to track the $experiment_started event From 8085a7dc15d339cabce0379e2d2baebfbba61e77 Mon Sep 17 00:00:00 2001 From: Kwame Efah Date: Mon, 29 Sep 2025 16:18:26 -0700 Subject: [PATCH 13/13] Fix broken python page link --- pages/docs/featureflags.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx index 7dd864774b..0e7b92f59a 100644 --- a/pages/docs/featureflags.mdx +++ b/pages/docs/featureflags.mdx @@ -148,7 +148,7 @@ See our developer guides on implementing feature flags on these platforms below: - + Coming soon: React Native, Java, Ruby