diff --git a/cspell.json b/cspell.json
index 583e0e554d..315171ca8a 100644
--- a/cspell.json
+++ b/cspell.json
@@ -223,6 +223,7 @@
"Langfuse",
"langfuse",
"Leanplum",
+ "Logcat",
"logit",
"logotable",
"Lookback",
@@ -271,6 +272,7 @@
"onesignal",
"OADA",
"openapi",
+ "openfeature",
"openviewpartners",
"operationalize",
"operationalized",
diff --git a/pages/docs/featureflags.mdx b/pages/docs/featureflags.mdx
index 1d52a01f2f..1660fabc31 100644
--- a/pages/docs/featureflags.mdx
+++ b/pages/docs/featureflags.mdx
@@ -253,6 +253,28 @@ See our developer guides on implementing feature flags on these platforms below:
+### OpenFeature Providers
+
+Mixpanel also offers [OpenFeature](https://openfeature.dev/) providers, which let you use Mixpanel's feature flags through OpenFeature's standardized, vendor-agnostic API.
+
+#### Client Side
+
+
+
+
+
+
+
+#### Server Side
+
+
+
+
+
+
+
+
+
If you'd like to see Feature Flags availability in other SDKs, please [reach out to the Support team](https://mixpanel.com/get-support).
diff --git a/pages/docs/tracking-methods/sdks/android/_meta.ts b/pages/docs/tracking-methods/sdks/android/_meta.ts
index 5ee586c759..4c5d58100f 100644
--- a/pages/docs/tracking-methods/sdks/android/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/android/_meta.ts
@@ -1,4 +1,5 @@
export default {
"android-replay": "Session Replay (Android)",
- "android-flags": "Feature Flags (Android)"
+ "android-flags": "Feature Flags (Android)",
+ "android-openfeature": "OpenFeature Provider (Android)",
}
diff --git a/pages/docs/tracking-methods/sdks/android/android-openfeature.mdx b/pages/docs/tracking-methods/sdks/android/android-openfeature.mdx
new file mode 100644
index 0000000000..02e54d77eb
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/android/android-openfeature.mdx
@@ -0,0 +1,189 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Android)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Android OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Android)](/docs/tracking-methods/sdks/android/android-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Android SDK 21+
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+Add to your `build.gradle.kts`:
+
+```kotlin
+dependencies {
+ implementation("com.mixpanel.android:mixpanel-android-openfeature:")
+ implementation("dev.openfeature:kotlin-sdk-android:0.7.2")
+}
+```
+
+## Quick Start
+
+```kotlin
+import com.mixpanel.android.openfeature.MixpanelProvider
+import com.mixpanel.android.mpmetrics.MixpanelOptions
+import dev.openfeature.kotlin.sdk.OpenFeatureAPI
+
+// 1. Create the provider
+val options = MixpanelOptions.Builder()
+ .featureFlags()
+ .build()
+val provider = MixpanelProvider(context, "YOUR_PROJECT_TOKEN", options)
+
+// 2. Register the provider with OpenFeature
+OpenFeatureAPI.setProviderAndWait(provider)
+
+// 3. Get a client and evaluate flags
+val client = OpenFeatureAPI.getClient()
+val showNewFeature = client.getBooleanValue("new-feature-flag", false)
+
+if (showNewFeature) {
+ // New feature is enabled!
+}
+```
+
+### Using an Existing MixpanelAPI Instance
+
+```kotlin
+import com.mixpanel.android.mpmetrics.MixpanelAPI
+
+val mixpanel = MixpanelAPI.getInstance(context, "YOUR_PROJECT_TOKEN", false, options)
+val provider = MixpanelProvider(mixpanel.getFlags())
+
+OpenFeatureAPI.setProviderAndWait(provider)
+```
+
+
+This provider does **not** call `mixpanel.identify()` or `mixpanel.track()`. If you need to update the logged-in user or use [Runtime Events](/docs/featureflags/runtime-events) for targeting, call these methods on the **same `MixpanelAPI` instance** whose `Flags` object was passed to the provider.
+
+
+```kotlin
+val provider = MixpanelProvider(context, "YOUR_PROJECT_TOKEN", options)
+
+// Use the same instance for identity and tracking
+provider.mixpanel?.identify("user-123")
+provider.mixpanel?.track("Purchase Completed")
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `getBooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `getBooleanValue()`, `getStringValue()`, `getIntegerValue()`, `getDoubleValue()`, or `getObjectValue()` |
+| Dynamic Config | JSON object | `getObjectValue()` |
+
+```kotlin
+val client = OpenFeatureAPI.getClient()
+
+// Feature Gate
+val isFeatureOn = client.getBooleanValue("new-checkout", false)
+
+// Experiment with string variants
+val buttonColor = client.getStringValue("button-color-test", "blue")
+
+// Experiment with numeric variants
+val maxItems = client.getIntegerValue("max-items", 10)
+val threshold = client.getDoubleValue("score-threshold", 0.5)
+
+// Dynamic Config
+val featureConfig = client.getObjectValue("homepage-layout", Value.Structure(mapOf(
+ "layout" to Value.String("grid"),
+ "itemsPerRow" to Value.Integer(3)
+)))
+```
+
+### Evaluation Context
+
+Context must be set globally via `OpenFeatureAPI.setContext()`:
+
+```kotlin
+import dev.openfeature.kotlin.sdk.ImmutableContext
+import dev.openfeature.kotlin.sdk.Value
+
+OpenFeatureAPI.setContext(ImmutableContext(
+ attributes = mutableMapOf(
+ "email" to Value.String("user@example.com"),
+ "plan" to Value.String("premium")
+ )
+))
+```
+
+
+Per-evaluation context (the optional `context` parameter on evaluation methods) is **not supported** by this provider. Context must be set globally via `OpenFeatureAPI.setContext()`, which triggers a re-fetch of flag values from Mixpanel.
+
+
+### Runtime Properties
+
+Pass `custom_properties` in the evaluation context for runtime targeting:
+
+```kotlin
+OpenFeatureAPI.setContext(ImmutableContext(
+ attributes = mutableMapOf(
+ "custom_properties" to Value.Structure(mapOf(
+ "tier" to Value.String("enterprise"),
+ "seats" to Value.Integer(50),
+ ))
+ )
+))
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```kotlin
+val details = client.getBooleanDetails("my-feature", false)
+
+println(details.value)
+println(details.variant)
+println(details.reason)
+println(details.errorCode)
+```
+
+### User Identity
+
+This provider does **not** call `mixpanel.identify()`. Manage identity through the same Mixpanel instance:
+
+```kotlin
+provider.mixpanel?.identify("user-123")
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the provider has finished initializing |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Feature flags not enabled:** Ensure MixpanelOptions includes `.featureFlags()`.
+2. **Provider not ready:** Use `setProviderAndWait` to ensure initialization.
+3. **Network issues:** Check Logcat for failed requests.
+4. **Flag not configured:** Verify the flag exists and is enabled.
+
+### Flags Not Updating After Context Change
+
+Update context and the provider will re-fetch flags:
+
+```kotlin
+OpenFeatureAPI.setContext(ImmutableContext(
+ attributes = mutableMapOf("plan" to Value.String("premium"))
+))
+```
diff --git a/pages/docs/tracking-methods/sdks/go/_meta.ts b/pages/docs/tracking-methods/sdks/go/_meta.ts
index 2d7221cfd8..07d9df4915 100644
--- a/pages/docs/tracking-methods/sdks/go/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/go/_meta.ts
@@ -1,3 +1,4 @@
export default {
"go-flags": "Feature Flags (Go)",
+ "go-openfeature": "OpenFeature Provider (Go)",
}
diff --git a/pages/docs/tracking-methods/sdks/go/go-openfeature.mdx b/pages/docs/tracking-methods/sdks/go/go-openfeature.mdx
new file mode 100644
index 0000000000..ba7da0ca38
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/go/go-openfeature.mdx
@@ -0,0 +1,178 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Go)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Go OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Go)](/docs/tracking-methods/sdks/go/go-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+```bash
+go get github.com/mixpanel/mixpanel-go/openfeature
+go get github.com/open-feature/go-sdk
+```
+
+## Quick Start
+
+```go
+package main
+
+import (
+ "context"
+ "fmt"
+
+ mixpanelopenfeature "github.com/mixpanel/mixpanel-go/openfeature"
+ "github.com/mixpanel/mixpanel-go/v2/flags"
+ of "github.com/open-feature/go-sdk/openfeature"
+)
+
+func main() {
+ // 1. Create the Mixpanel OpenFeature provider with local evaluation
+ provider, err := mixpanelopenfeature.NewProviderWithLocalConfig("YOUR_PROJECT_TOKEN", flags.LocalFlagsConfig{})
+ if err != nil {
+ panic(err)
+ }
+
+ // 2. Register the provider with OpenFeature
+ of.SetProvider(provider)
+ client := of.NewClient("my-app")
+
+ // 3. Evaluate flags
+ showNewFeature, _ := client.BooleanValue(context.Background(), "new-feature-flag", false, of.EvaluationContext{})
+
+ if showNewFeature {
+ fmt.Println("New feature is enabled!")
+ }
+}
+```
+
+## Initialization
+
+### Local Evaluation (Recommended)
+
+Flag definitions are fetched from Mixpanel and evaluated locally. This is faster and works offline after the initial fetch.
+
+
+Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode.
+
+
+```go
+provider, err := mixpanelopenfeature.NewProviderWithLocalConfig("YOUR_PROJECT_TOKEN", flags.LocalFlagsConfig{})
+```
+
+### Remote Evaluation
+
+Each flag evaluation makes a request to Mixpanel's servers.
+
+```go
+provider, err := mixpanelopenfeature.NewProviderWithRemoteConfig("YOUR_PROJECT_TOKEN", flags.RemoteFlagsConfig{})
+```
+
+### Using an Existing Mixpanel Instance
+
+```go
+mp := mixpanel.NewApiClient("YOUR_TOKEN", mixpanel.WithLocalFlags(flags.LocalFlagsConfig{}))
+mp.LocalFlags.StartPollingForDefinitions(context.Background())
+
+provider, err := mixpanelopenfeature.NewProvider(mp.LocalFlags)
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `BooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `BooleanValue()`, `StringValue()`, `FloatValue()`, `IntValue()`, or `ObjectValue()` |
+| Dynamic Config | JSON object | `ObjectValue()` |
+
+```go
+ctx := context.Background()
+evalCtx := of.EvaluationContext{}
+
+// Feature Gate
+enabled, _ := client.BooleanValue(ctx, "new-checkout", false, evalCtx)
+
+// Experiment with string variants
+buttonColor, _ := client.StringValue(ctx, "button-color-test", "blue", evalCtx)
+
+// Numeric flags
+threshold, _ := client.FloatValue(ctx, "score-threshold", 0.5, evalCtx)
+maxItems, _ := client.IntValue(ctx, "max-items", 10, evalCtx)
+
+// Dynamic Config
+config, _ := client.ObjectValue(ctx, "homepage-layout", map[string]any{
+ "layout": "grid",
+}, evalCtx)
+```
+
+### Evaluation Context
+
+```go
+evalCtx := of.NewEvaluationContext("user-123", map[string]any{
+ "email": "user@example.com",
+ "plan": "premium",
+})
+
+enabled, _ := client.BooleanValue(ctx, "premium-feature", false, evalCtx)
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```go
+details, _ := client.BooleanValueDetails(ctx, "my-feature", false, of.EvaluationContext{})
+
+fmt.Println(details.Value)
+fmt.Println(details.Variant)
+fmt.Println(details.Reason)
+fmt.Println(details.ErrorCode)
+```
+
+### Accessing the Underlying Mixpanel Client
+
+```go
+provider, _ := mixpanelopenfeature.NewProviderWithLocalConfig("YOUR_TOKEN", flags.LocalFlagsConfig{})
+
+provider.Mixpanel.Track(ctx, []*mixpanel.Event{
+ {Name: "button_clicked", Properties: map[string]any{"color": "blue"}},
+})
+```
+
+### Shutdown
+
+```go
+provider.Shutdown()
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the local provider has finished fetching definitions |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready:** Ensure polling has started and definitions have been received.
+2. **Flag not configured:** Verify the flag exists and is enabled in your Mixpanel project.
+3. **Network issues:** For remote evaluation, check that your application can reach Mixpanel's API.
+
+### Type Mismatch Errors
+
+The flag's value type must match the evaluation method. `IntValue()` accepts whole-number `float64` values. `FloatValue()` accepts any numeric type.
diff --git a/pages/docs/tracking-methods/sdks/java/_meta.ts b/pages/docs/tracking-methods/sdks/java/_meta.ts
index 534176a476..de3f9c9547 100644
--- a/pages/docs/tracking-methods/sdks/java/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/java/_meta.ts
@@ -1,4 +1,5 @@
export default {
"index": "Java",
"java-flags": "Feature Flags (Java)",
+ "java-openfeature": "OpenFeature Provider (Java)",
}
\ No newline at end of file
diff --git a/pages/docs/tracking-methods/sdks/java/java-openfeature.mdx b/pages/docs/tracking-methods/sdks/java/java-openfeature.mdx
new file mode 100644
index 0000000000..3e3918a355
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/java/java-openfeature.mdx
@@ -0,0 +1,186 @@
+import { Callout } from "nextra/components";
+
+# OpenFeature Provider (Java)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Java OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Java)](/docs/tracking-methods/sdks/java/java-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Java 8 or higher
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+### Maven
+
+```xml
+
+ com.mixpanel
+ mixpanel-java-openfeature
+ 0.1.0
+
+
+ dev.openfeature
+ sdk
+ 1.20.1
+
+```
+
+### Gradle
+
+```groovy
+implementation 'com.mixpanel:mixpanel-java-openfeature:0.1.0'
+implementation 'dev.openfeature:sdk:1.20.1'
+```
+
+## Quick Start
+
+```java
+import com.mixpanel.openfeature.MixpanelProvider;
+import com.mixpanel.mixpanelapi.featureflags.config.LocalFlagsConfig;
+import dev.openfeature.sdk.OpenFeatureAPI;
+import dev.openfeature.sdk.Client;
+
+// 1. Create and register the provider with local evaluation
+MixpanelProvider provider = new MixpanelProvider(
+ "YOUR_PROJECT_TOKEN",
+ new LocalFlagsConfig("YOUR_PROJECT_TOKEN")
+);
+OpenFeatureAPI api = OpenFeatureAPI.getInstance();
+api.setProvider(provider);
+
+// 2. Get a client and evaluate flags
+Client client = api.getClient();
+boolean showNewFeature = client.getBooleanValue("new-feature-flag", false);
+
+if (showNewFeature) {
+ System.out.println("New feature is enabled!");
+}
+```
+
+## Initialization
+
+### Local Evaluation (Recommended)
+
+
+Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode.
+
+
+```java
+MixpanelProvider provider = new MixpanelProvider(
+ "YOUR_PROJECT_TOKEN",
+ new LocalFlagsConfig("YOUR_PROJECT_TOKEN")
+);
+```
+
+### Remote Evaluation
+
+```java
+MixpanelProvider provider = new MixpanelProvider(
+ "YOUR_PROJECT_TOKEN",
+ new RemoteFlagsConfig("YOUR_PROJECT_TOKEN")
+);
+```
+
+### Using an Existing MixpanelAPI Instance
+
+```java
+MixpanelAPI mixpanel = new MixpanelAPI(new LocalFlagsConfig("YOUR_PROJECT_TOKEN"));
+LocalFlagsProvider localFlags = mixpanel.getLocalFlags();
+localFlags.startPollingForDefinitions();
+
+MixpanelProvider provider = new MixpanelProvider(localFlags);
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `getBooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `getBooleanValue()`, `getStringValue()`, `getIntegerValue()`, `getDoubleValue()`, or `getObjectValue()` |
+| Dynamic Config | JSON object | `getObjectValue()` |
+
+```java
+Client client = api.getClient();
+
+// Feature Gate
+boolean isFeatureOn = client.getBooleanValue("new-checkout", false);
+
+// Experiment with string variants
+String buttonColor = client.getStringValue("button-color-test", "blue");
+
+// Experiment with numeric variants
+int maxItems = client.getIntegerValue("max-items", 10);
+double threshold = client.getDoubleValue("score-threshold", 0.5);
+
+// Dynamic Config
+Value featureConfig = client.getObjectValue("homepage-layout", new Value("default"));
+```
+
+### Evaluation Context
+
+```java
+MutableContext context = new MutableContext();
+context.setTargetingKey("user-123");
+context.add("email", "user@example.com");
+context.add("plan", "premium");
+context.add("beta_tester", true);
+
+boolean value = client.getBooleanValue("premium-feature", false, context);
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```java
+FlagEvaluationDetails details = client.getBooleanDetails("my-feature", false);
+
+System.out.println(details.getValue());
+System.out.println(details.getVariant());
+System.out.println(details.getReason());
+System.out.println(details.getErrorCode());
+```
+
+### Accessing the Underlying MixpanelAPI
+
+```java
+MixpanelAPI mixpanel = provider.getMixpanel();
+```
+
+### Shutdown
+
+```java
+provider.shutdown();
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the local provider has finished loading definitions |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready:** Flag definitions are polled asynchronously. Allow time for the initial fetch.
+2. **Invalid project token:** Verify the token matches your Mixpanel project.
+3. **Flag not configured:** Verify the flag exists and is enabled.
+
+### Type Mismatch Errors
+
+1. Verify the flag's value type matches your evaluation method.
+2. Use `getObjectValue()` for JSON objects.
+3. Integer evaluation accepts `Long` and whole-number `Double` values within `Integer` bounds. Double evaluation accepts any numeric type.
diff --git a/pages/docs/tracking-methods/sdks/javascript/_meta.ts b/pages/docs/tracking-methods/sdks/javascript/_meta.ts
index e0a438591d..c79fefa139 100644
--- a/pages/docs/tracking-methods/sdks/javascript/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/javascript/_meta.ts
@@ -1,4 +1,5 @@
export default {
"javascript-replay": "Session Replay (Javascript)",
"javascript-flags": "Feature Flags (Javascript)",
+ "javascript-openfeature": "OpenFeature Provider (Web)",
}
diff --git a/pages/docs/tracking-methods/sdks/javascript/javascript-openfeature.mdx b/pages/docs/tracking-methods/sdks/javascript/javascript-openfeature.mdx
new file mode 100644
index 0000000000..1ace7c1db7
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/javascript/javascript-openfeature.mdx
@@ -0,0 +1,198 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Web)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Web OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Web)](/docs/tracking-methods/sdks/javascript/javascript-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+```bash
+npm install @mixpanel/openfeature-web-provider @openfeature/web-sdk mixpanel-browser
+```
+
+## Quick Start
+
+```typescript
+import mixpanel from 'mixpanel-browser';
+import { OpenFeature } from '@openfeature/web-sdk';
+import { MixpanelProvider } from '@mixpanel/openfeature-web-provider';
+
+// 1. Initialize Mixpanel with feature flags
+mixpanel.init('YOUR_PROJECT_TOKEN', {
+ flags: {
+ context: { plan: 'premium' }
+ }
+});
+
+// 2. Create and register the Mixpanel provider
+const provider = new MixpanelProvider(mixpanel.flags);
+await OpenFeature.setProviderAndWait(provider);
+
+// 3. Get a client and evaluate flags
+const client = OpenFeature.getClient();
+const showNewFeature = client.getBooleanValue('new-feature-flag', false);
+
+if (showNewFeature) {
+ console.log('New feature is enabled!');
+}
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `getBooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `getBooleanValue()`, `getStringValue()`, `getNumberValue()`, or `getObjectValue()` |
+| Dynamic Config | JSON object | `getObjectValue()` |
+
+```typescript
+const client = OpenFeature.getClient();
+
+// Feature Gate
+const isFeatureOn = client.getBooleanValue('new-checkout', false);
+
+// Experiment with string variants
+const buttonColor = client.getStringValue('button-color-test', 'blue');
+
+// Experiment with number variants
+const maxItems = client.getNumberValue('max-items', 10);
+
+// Dynamic Config
+const featureConfig = client.getObjectValue('homepage-layout', {
+ layout: 'grid',
+ itemsPerRow: 3
+});
+```
+
+### Evaluation Context
+
+Context must be set globally via `OpenFeature.setContext()`:
+
+```typescript
+await OpenFeature.setContext({
+ email: 'user@example.com',
+ plan: 'premium'
+});
+```
+
+
+Per-evaluation context (the optional third argument to evaluation methods) is **not supported** by this provider. Context must be set globally via `OpenFeature.setContext()`, which triggers a re-fetch of flag values from Mixpanel.
+
+
+### Runtime Properties
+
+Pass `custom_properties` in the evaluation context for runtime targeting:
+
+```typescript
+await OpenFeature.setContext({
+ custom_properties: {
+ tier: 'enterprise',
+ seats: 50,
+ industry: 'technology'
+ }
+});
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```typescript
+const details = client.getBooleanDetails('my-feature', false);
+
+console.log(details.value);
+console.log(details.variant);
+console.log(details.reason);
+console.log(details.errorCode);
+```
+
+### React Integration
+
+```tsx
+import { OpenFeatureProvider, useBooleanFlagValue } from '@openfeature/react-sdk';
+import { OpenFeature } from '@openfeature/web-sdk';
+import mixpanel from 'mixpanel-browser';
+import { MixpanelProvider } from '@mixpanel/openfeature-web-provider';
+
+// Initialize outside of component
+mixpanel.init('YOUR_PROJECT_TOKEN', {
+ flags: {
+ context: { plan: 'premium' }
+ }
+});
+const provider = new MixpanelProvider(mixpanel.flags);
+OpenFeature.setProvider(provider);
+
+function App() {
+ return (
+
+
+
+ );
+}
+
+function MyComponent() {
+ const showBanner = useBooleanFlagValue('show-banner', false);
+
+ return (
+
+ {showBanner && }
+
+ );
+}
+```
+
+### User Identity
+
+This provider does **not** call `mixpanel.identify()`. Manage identity through Mixpanel directly:
+
+```typescript
+mixpanel.identify('user-123');
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the provider has finished initializing |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+To avoid `PROVIDER_NOT_READY`, use `setProviderAndWait`:
+
+```typescript
+await OpenFeature.setProviderAndWait(provider);
+```
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Feature flags not enabled:** Ensure Mixpanel was initialized with `flags` enabled:
+ ```typescript
+ mixpanel.init('YOUR_TOKEN', { flags: { context: { plan: 'premium' } } });
+ ```
+2. **Provider not ready:** Use `setProviderAndWait` to ensure initialization.
+3. **Network issues:** Check the browser console for failed requests.
+4. **Flag not configured:** Verify the flag exists and is enabled.
+
+### Flags Not Updating After Context Change
+
+Update context and the provider will re-fetch flags:
+
+```typescript
+await OpenFeature.setContext({ plan: 'premium' });
+```
diff --git a/pages/docs/tracking-methods/sdks/nodejs/_meta.ts b/pages/docs/tracking-methods/sdks/nodejs/_meta.ts
index 01a0e4d9dd..1327af91c4 100644
--- a/pages/docs/tracking-methods/sdks/nodejs/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/nodejs/_meta.ts
@@ -1,3 +1,4 @@
export default {
"nodejs-flags": "Feature Flags (Node.js)",
+ "nodejs-openfeature": "OpenFeature Provider (Node.js)",
}
diff --git a/pages/docs/tracking-methods/sdks/nodejs/nodejs-openfeature.mdx b/pages/docs/tracking-methods/sdks/nodejs/nodejs-openfeature.mdx
new file mode 100644
index 0000000000..ccf6b0e58c
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/nodejs/nodejs-openfeature.mdx
@@ -0,0 +1,167 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Node.js)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Node.js OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Node.js)](/docs/tracking-methods/sdks/nodejs/nodejs-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Node.js 10 or higher
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+```bash
+npm install @mixpanel/openfeature-server-provider @openfeature/server-sdk mixpanel
+```
+
+## Quick Start
+
+```typescript
+import { OpenFeature } from "@openfeature/server-sdk";
+import { MixpanelProvider } from "@mixpanel/openfeature-server-provider";
+
+// 1. Create and register the provider with local evaluation
+const provider = MixpanelProvider.createLocal("YOUR_PROJECT_TOKEN");
+await OpenFeature.setProviderAndWait(provider);
+
+// 2. Get a client and evaluate flags
+const client = OpenFeature.getClient();
+const showNewFeature = await client.getBooleanValue("new-feature-flag", false, {
+ distinct_id: "user-123",
+});
+
+if (showNewFeature) {
+ console.log("New feature is enabled!");
+}
+```
+
+## Initialization
+
+### Local Evaluation (Recommended)
+
+
+Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode.
+
+
+```typescript
+const provider = MixpanelProvider.createLocal("YOUR_PROJECT_TOKEN");
+```
+
+### Remote Evaluation
+
+```typescript
+const provider = MixpanelProvider.createRemote("YOUR_PROJECT_TOKEN");
+```
+
+### Using an Existing Mixpanel Instance
+
+```typescript
+import Mixpanel from "mixpanel";
+
+const mixpanel = Mixpanel.init("YOUR_PROJECT_TOKEN", {
+ local_flags_config: {},
+});
+const localFlags = mixpanel.local_flags!;
+localFlags.startPollingForDefinitions();
+
+const provider = new MixpanelProvider(localFlags);
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `getBooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `getBooleanValue()`, `getStringValue()`, `getNumberValue()`, or `getObjectValue()` |
+| Dynamic Config | JSON object | `getObjectValue()` |
+
+```typescript
+const client = OpenFeature.getClient();
+const context = { distinct_id: "user-123" };
+
+// Feature Gate
+const isFeatureOn = await client.getBooleanValue("new-checkout", false, context);
+
+// Experiment with string variants
+const buttonColor = await client.getStringValue("button-color-test", "blue", context);
+
+// Experiment with number variants
+const maxItems = await client.getNumberValue("max-items", 10, context);
+
+// Dynamic Config
+const featureConfig = await client.getObjectValue("homepage-layout", {}, context);
+```
+
+### Evaluation Context
+
+```typescript
+// Global context
+OpenFeature.setContext({ environment: "production" });
+
+// Per-evaluation context (merged with and overrides global context)
+const value = await client.getBooleanValue("premium-feature", false, {
+ distinct_id: "user-123",
+ email: "user@example.com",
+ plan: "premium",
+});
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```typescript
+const details = await client.getBooleanDetails("my-feature", false, {
+ distinct_id: "user-123",
+});
+
+console.log(details.value);
+console.log(details.variant);
+console.log(details.reason);
+console.log(details.errorCode);
+```
+
+### Accessing the Underlying Mixpanel Instance
+
+```typescript
+const mixpanel = provider.mixpanel;
+if (mixpanel) {
+ mixpanel.track("button_clicked", { distinct_id: "user-123" });
+}
+```
+
+### Shutdown
+
+```typescript
+await OpenFeature.close();
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the local provider has finished loading definitions |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready:** Use `setProviderAndWait()` to ensure flags are ready before evaluation.
+2. **Invalid project token:** Verify the token matches your Mixpanel project.
+3. **Flag not configured:** Verify the flag exists and is enabled.
+
+### Type Mismatch Errors
+
+Verify the flag's value type matches your evaluation method. Use `getObjectValue()` for JSON objects.
diff --git a/pages/docs/tracking-methods/sdks/python/_meta.ts b/pages/docs/tracking-methods/sdks/python/_meta.ts
index 2f8a88bad9..26d9e67855 100644
--- a/pages/docs/tracking-methods/sdks/python/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/python/_meta.ts
@@ -1,3 +1,4 @@
export default {
"python-flags": "Feature Flags (Python)",
+ "python-openfeature": "OpenFeature Provider (Python)",
}
diff --git a/pages/docs/tracking-methods/sdks/python/python-openfeature.mdx b/pages/docs/tracking-methods/sdks/python/python-openfeature.mdx
new file mode 100644
index 0000000000..ffd33bd04d
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/python/python-openfeature.mdx
@@ -0,0 +1,193 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Python)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Python OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Python)](/docs/tracking-methods/sdks/python/python-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Python 3.9 or higher
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+```bash
+pip install mixpanel-openfeature openfeature-sdk
+```
+
+## Quick Start
+
+```python
+from mixpanel_openfeature import MixpanelProvider
+from mixpanel.flags.types import LocalFlagsConfig
+from openfeature import api
+
+# 1. Create and register the provider with local evaluation
+provider = MixpanelProvider.from_local_config(
+ "YOUR_PROJECT_TOKEN",
+ LocalFlagsConfig(token="YOUR_PROJECT_TOKEN"),
+)
+api.set_provider(provider)
+
+# 2. Get a client and evaluate flags
+client = api.get_client()
+show_new_feature = client.get_boolean_value("new-feature-flag", False)
+
+if show_new_feature:
+ print("New feature is enabled!")
+```
+
+## Initialization
+
+The provider supports three initialization methods depending on your evaluation strategy.
+
+### Local Evaluation (Recommended)
+
+Evaluates flags locally using cached flag definitions polled from Mixpanel. This minimizes latency since there is no network call at evaluation time.
+
+
+Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode.
+
+
+```python
+from mixpanel_openfeature import MixpanelProvider
+from mixpanel.flags.types import LocalFlagsConfig
+
+provider = MixpanelProvider.from_local_config(
+ "YOUR_PROJECT_TOKEN",
+ LocalFlagsConfig(token="YOUR_PROJECT_TOKEN"),
+)
+```
+
+### Remote Evaluation
+
+Evaluates flags by making a request to Mixpanel's servers for each evaluation. Use this when you need real-time flag values or cohort-based targeting.
+
+```python
+from mixpanel_openfeature import MixpanelProvider
+from mixpanel.flags.types import RemoteFlagsConfig
+
+provider = MixpanelProvider.from_remote_config(
+ "YOUR_PROJECT_TOKEN",
+ RemoteFlagsConfig(token="YOUR_PROJECT_TOKEN"),
+)
+```
+
+### Using an Existing Mixpanel Instance
+
+If your application already has a `Mixpanel` instance configured for tracking, you can wrap its flags provider:
+
+```python
+from mixpanel import Mixpanel
+from mixpanel.flags.types import LocalFlagsConfig
+from mixpanel_openfeature import MixpanelProvider
+
+mp = Mixpanel("YOUR_PROJECT_TOKEN", local_flags_config=LocalFlagsConfig(token="YOUR_PROJECT_TOKEN"))
+mp.local_flags.start_polling_for_definitions()
+
+provider = MixpanelProvider(mp.local_flags)
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `True` / `False` | `get_boolean_value()` |
+| Experiment | boolean, string, number, or JSON object | `get_boolean_value()`, `get_string_value()`, `get_integer_value()`, `get_float_value()`, or `get_object_value()` |
+| Dynamic Config | JSON object | `get_object_value()` |
+
+```python
+client = api.get_client()
+
+# Feature Gate
+is_feature_on = client.get_boolean_value("new-checkout", False)
+
+# Experiment with string variants
+button_color = client.get_string_value("button-color-test", "blue")
+
+# Experiment with numeric variants
+max_items = client.get_integer_value("max-items", 10)
+threshold = client.get_float_value("score-threshold", 0.5)
+
+# Dynamic Config
+feature_config = client.get_object_value("homepage-layout", {"layout": "default"})
+```
+
+### Evaluation Context
+
+Pass context to provide user attributes for targeting:
+
+```python
+from openfeature.evaluation_context import EvaluationContext
+
+context = EvaluationContext(
+ targeting_key="user-123",
+ attributes={
+ "email": "user@example.com",
+ "plan": "premium",
+ "beta_tester": True,
+ },
+)
+
+value = client.get_boolean_value("premium-feature", False, context)
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```python
+details = client.get_boolean_details("my-feature", False)
+
+print(details.value) # The resolved value
+print(details.variant) # The variant key from Mixpanel
+print(details.reason) # Why this value was returned
+print(details.error_code) # Error code if evaluation failed
+```
+
+### Accessing the Underlying Mixpanel Instance
+
+When using `from_local_config` or `from_remote_config`, you can access the Mixpanel instance for tracking:
+
+```python
+mp = provider.mixpanel
+```
+
+### Shutdown
+
+```python
+provider.shutdown()
+```
+
+## Error Handling
+
+The provider uses OpenFeature's standard error codes:
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before local provider has finished loading definitions |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready (local evaluation):** Flag definitions are polled asynchronously. Allow time for the initial fetch to complete.
+2. **Invalid project token:** Verify the token matches your Mixpanel project.
+3. **Flag not configured:** Verify the flag exists and is enabled in your Mixpanel project.
+
+### Type Mismatch Errors
+
+1. Verify the flag's value type in Mixpanel matches your evaluation method (e.g., string `"true"` requires `get_string_value()`, not `get_boolean_value()`).
+2. Use `get_object_value()` for JSON objects.
+3. Integer evaluation accepts whole-number `float` values. Float evaluation accepts any numeric type.
diff --git a/pages/docs/tracking-methods/sdks/ruby/_meta.ts b/pages/docs/tracking-methods/sdks/ruby/_meta.ts
index f7acbe4f14..1e4e2354db 100644
--- a/pages/docs/tracking-methods/sdks/ruby/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/ruby/_meta.ts
@@ -1,3 +1,4 @@
export default {
"ruby-flags": "Feature Flags (Ruby)",
+ "ruby-openfeature": "OpenFeature Provider (Ruby)",
}
diff --git a/pages/docs/tracking-methods/sdks/ruby/ruby-openfeature.mdx b/pages/docs/tracking-methods/sdks/ruby/ruby-openfeature.mdx
new file mode 100644
index 0000000000..2022b7da0c
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/ruby/ruby-openfeature.mdx
@@ -0,0 +1,203 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Ruby)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Ruby OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Ruby)](/docs/tracking-methods/sdks/ruby/ruby-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- Ruby 3.1.0 or higher
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+Add to your `Gemfile`:
+
+```ruby
+gem 'mixpanel-ruby-openfeature'
+gem 'openfeature-sdk'
+gem 'mixpanel-ruby'
+```
+
+Then run:
+
+```bash
+bundle install
+```
+
+## Quick Start
+
+```ruby
+require 'mixpanel-ruby'
+require 'mixpanel/openfeature'
+
+# 1. Create the provider with local evaluation
+provider = Mixpanel::OpenFeature::Provider.from_local(
+ 'YOUR_PROJECT_TOKEN',
+ { poll_interval: 300 }
+)
+
+# 2. Register the provider with OpenFeature
+OpenFeature::SDK.configure do |config|
+ config.set_provider(provider)
+end
+
+# 3. Get a client and evaluate flags
+client = OpenFeature::SDK.build_client
+
+show_new_feature = client.fetch_boolean_value(flag_key: 'new-feature-flag', default_value: false)
+
+if show_new_feature
+ puts 'New feature is enabled!'
+end
+```
+
+## Initialization
+
+### Local Evaluation (Recommended)
+
+Downloads flag definitions and evaluates them locally with no per-evaluation network requests.
+
+
+Targeting by Mixpanel cohorts and sticky variants are not supported in Local Evaluation mode.
+
+
+```ruby
+provider = Mixpanel::OpenFeature::Provider.from_local(
+ 'YOUR_PROJECT_TOKEN',
+ { poll_interval: 300 }
+)
+```
+
+### Remote Evaluation
+
+Sends each flag check to Mixpanel's servers.
+
+```ruby
+provider = Mixpanel::OpenFeature::Provider.from_remote(
+ 'YOUR_PROJECT_TOKEN',
+ {}
+)
+```
+
+### Using an Existing Tracker
+
+```ruby
+tracker = Mixpanel::Tracker.new('YOUR_PROJECT_TOKEN', nil, local_flags_config: { poll_interval: 300 })
+tracker.local_flags.start_polling_for_definitions!
+
+provider = Mixpanel::OpenFeature::Provider.new(tracker.local_flags)
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `fetch_boolean_value` |
+| Experiment | boolean, string, number, or JSON object | `fetch_boolean_value`, `fetch_string_value`, `fetch_number_value`, or `fetch_object_value` |
+| Dynamic Config | JSON object | `fetch_object_value` |
+
+```ruby
+client = OpenFeature::SDK.build_client
+
+# Feature Gate
+is_feature_on = client.fetch_boolean_value(flag_key: 'new-checkout', default_value: false)
+
+# Experiment with string variants
+button_color = client.fetch_string_value(flag_key: 'button-color-test', default_value: 'blue')
+
+# Experiment with number variants
+max_items = client.fetch_number_value(flag_key: 'max-items', default_value: 10)
+
+# Dynamic Config
+feature_config = client.fetch_object_value(
+ flag_key: 'homepage-layout',
+ default_value: { 'layout' => 'grid', 'items_per_row' => 3 }
+)
+```
+
+### Evaluation Context
+
+```ruby
+context = OpenFeature::SDK::EvaluationContext.new(
+ targeting_key: 'user-123',
+ email: 'user@example.com',
+ plan: 'premium'
+)
+
+value = client.fetch_boolean_value(
+ flag_key: 'premium-feature',
+ default_value: false,
+ evaluation_context: context
+)
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```ruby
+details = client.fetch_boolean_details(flag_key: 'my-feature', default_value: false)
+
+puts details.value
+puts details.variant
+puts details.reason
+puts details.error_code
+```
+
+### Accessing the Mixpanel Tracker
+
+```ruby
+provider.mixpanel.track('user-123', 'Page View', { 'page' => '/home' })
+```
+
+### Rails Integration
+
+```ruby
+# config/initializers/openfeature.rb
+provider = Mixpanel::OpenFeature::Provider.from_local(
+ ENV['MIXPANEL_TOKEN'],
+ { poll_interval: 300 }
+)
+
+OpenFeature::SDK.configure do |config|
+ config.set_provider(provider)
+end
+
+at_exit { provider.shutdown }
+```
+
+### Shutdown
+
+```ruby
+provider.shutdown
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the provider has finished initializing |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready:** Flag definitions are fetched asynchronously. Allow time for the initial fetch.
+2. **Invalid project token:** Verify the token matches your Mixpanel project.
+3. **Flag not configured:** Verify the flag exists and is enabled.
+
+### Type Mismatch Errors
+
+Verify the flag's value type matches your evaluation method. Use `fetch_object_value` for JSON objects.
diff --git a/pages/docs/tracking-methods/sdks/swift/_meta.ts b/pages/docs/tracking-methods/sdks/swift/_meta.ts
index cae800483b..62775e5fcf 100644
--- a/pages/docs/tracking-methods/sdks/swift/_meta.ts
+++ b/pages/docs/tracking-methods/sdks/swift/_meta.ts
@@ -1,4 +1,5 @@
export default {
"swift-replay": "Session Replay (Swift)",
- "swift-flags": "Feature Flags (Swift)"
+ "swift-flags": "Feature Flags (Swift)",
+ "swift-openfeature": "OpenFeature Provider (Swift)",
}
diff --git a/pages/docs/tracking-methods/sdks/swift/swift-openfeature.mdx b/pages/docs/tracking-methods/sdks/swift/swift-openfeature.mdx
new file mode 100644
index 0000000000..372bd44b80
--- /dev/null
+++ b/pages/docs/tracking-methods/sdks/swift/swift-openfeature.mdx
@@ -0,0 +1,192 @@
+import { Callout } from 'nextra/components'
+
+# OpenFeature Provider (Swift)
+
+## Overview
+
+This guide covers using Mixpanel's [Feature Flags](/docs/featureflags) through the [OpenFeature](https://openfeature.dev/) standard with the Mixpanel Swift OpenFeature provider. OpenFeature provides a vendor-agnostic API for feature flag evaluation, allowing you to switch between providers without changing your application code.
+
+For the native Mixpanel SDK approach, see the [Feature Flags (Swift)](/docs/tracking-methods/sdks/swift/swift-flags) guide.
+
+## Prerequisites
+
+- Enterprise subscription plan with Feature Flags enabled
+- iOS 14.0+ / tvOS 14.0+ / macOS 11.0+ / watchOS 7.0+
+- Swift 5.5+
+- Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
+
+## Installation
+
+Add the following to your `Package.swift`:
+
+```swift
+dependencies: [
+ .package(url: "https://github.com/mixpanel/mixpanel-swift-openfeature", from: "0.1.0"),
+]
+```
+
+Then add `MixpanelOpenFeature` as a dependency of your target:
+
+```swift
+.target(
+ name: "YourTarget",
+ dependencies: [
+ .product(name: "MixpanelOpenFeature", package: "mixpanel-swift-openfeature"),
+ ]
+),
+```
+
+## Quick Start
+
+```swift
+import Mixpanel
+import MixpanelOpenFeature
+import OpenFeature
+
+// 1. Create and register the provider
+let options = MixpanelOptions(token: "YOUR_PROJECT_TOKEN")
+let provider = MixpanelOpenFeatureProvider(options: options)
+await OpenFeatureAPI.shared.setProviderAndWait(provider: provider)
+
+// 2. Get a client and evaluate flags
+let client = OpenFeatureAPI.shared.getClient()
+let showNewFeature = client.getBooleanValue(key: "new-feature-flag", defaultValue: false)
+
+if showNewFeature {
+ print("New feature is enabled!")
+}
+```
+
+### Using an Existing Mixpanel Instance
+
+```swift
+let flags = Mixpanel.mainInstance().flags
+let provider = MixpanelOpenFeatureProvider(flags: flags)
+await OpenFeatureAPI.shared.setProviderAndWait(provider: provider)
+```
+
+
+This provider does **not** call `mixpanel.identify()` or `mixpanel.track()`. If you need to update the logged-in user or use [Runtime Events](/docs/featureflags/runtime-events) for targeting, call these methods on the **same Mixpanel instance** that was passed to the provider.
+
+
+```swift
+// When using init(options:), access via provider.mixpanel
+provider.mixpanel?.identify(distinctId: "user-123")
+provider.mixpanel?.track(event: "Purchase", properties: ["amount": 49.99])
+
+// When using init(flags:), use the original instance
+let mixpanelInstance = Mixpanel.mainInstance()
+let provider = MixpanelOpenFeatureProvider(flags: mixpanelInstance.flags)
+mixpanelInstance.identify(distinctId: "user-123")
+```
+
+## Usage
+
+### Flag Types and Evaluation Methods
+
+| Mixpanel Flag Type | Variant Values | OpenFeature Method |
+|---|---|---|
+| Feature Gate | `true` / `false` | `getBooleanValue()` |
+| Experiment | boolean, string, number, or JSON object | `getBooleanValue()`, `getStringValue()`, `getIntegerValue()`, `getDoubleValue()`, or `getObjectValue()` |
+| Dynamic Config | JSON object | `getObjectValue()` |
+
+```swift
+let client = OpenFeatureAPI.shared.getClient()
+
+// Feature Gate
+let isFeatureOn = client.getBooleanValue(key: "new-checkout", defaultValue: false)
+
+// Experiment with string variants
+let buttonColor = client.getStringValue(key: "button-color-test", defaultValue: "blue")
+
+// Experiment with numeric variants
+let maxItems = client.getIntegerValue(key: "max-items", defaultValue: 10)
+let threshold = client.getDoubleValue(key: "score-threshold", defaultValue: 0.5)
+
+// Dynamic Config
+let featureConfig = client.getObjectValue(
+ key: "homepage-layout",
+ defaultValue: Value.structure(["layout": .string("grid"), "itemsPerRow": .integer(3)])
+)
+```
+
+### Evaluation Context
+
+Context must be set globally via `OpenFeatureAPI.shared.setEvaluationContext()`:
+
+```swift
+let ctx = MutableContext(
+ targetingKey: "user-123",
+ structure: MutableStructure(attributes: [
+ "email": .string("user@example.com"),
+ "plan": .string("premium"),
+ ])
+)
+await OpenFeatureAPI.shared.setEvaluationContext(evaluationContext: ctx)
+```
+
+### Runtime Properties
+
+Pass `custom_properties` in the evaluation context for [Runtime Properties](/docs/featureflags) targeting:
+
+```swift
+let ctx = MutableContext(
+ structure: MutableStructure(attributes: [
+ "custom_properties": .structure([
+ "tier": .string("enterprise"),
+ "seats": .integer(50),
+ ]),
+ ])
+)
+await OpenFeatureAPI.shared.setEvaluationContext(evaluationContext: ctx)
+```
+
+
+Unlike some providers, `targetingKey` is not used as a special bucketing key. It is passed as another context property. Mixpanel's server-side configuration determines which properties are used for targeting and bucketing.
+
+
+### Full Resolution Details
+
+```swift
+let details = client.getBooleanDetails(key: "my-feature", defaultValue: false)
+
+print(details.value)
+print(details.variant)
+print(details.reason)
+print(details.errorCode)
+```
+
+## Error Handling
+
+| Error Code | When |
+|---|---|
+| `PROVIDER_NOT_READY` | Flags evaluated before the provider has finished initializing |
+| `FLAG_NOT_FOUND` | The requested flag does not exist in Mixpanel |
+| `TYPE_MISMATCH` | The flag value type does not match the requested type |
+
+To avoid `PROVIDER_NOT_READY`, use `setProviderAndWait`:
+
+```swift
+await OpenFeatureAPI.shared.setProviderAndWait(provider: provider)
+```
+
+## Troubleshooting
+
+### Flags Always Return Default Values
+
+1. **Provider not ready:** Use `setProviderAndWait` to ensure initialization completes.
+2. **Network issues:** Check for failed requests to Mixpanel's flags API.
+3. **Flag not configured:** Verify the flag exists and is enabled in your Mixpanel project.
+
+### Flags Not Updating After Context Change
+
+When you update the OpenFeature context, the provider fetches new flag values:
+
+```swift
+let newCtx = MutableContext(
+ structure: MutableStructure(attributes: ["plan": .string("premium")])
+)
+await OpenFeatureAPI.shared.setEvaluationContext(evaluationContext: newCtx)
+```
+
+If flags still aren't updating, verify your targeting rules in Mixpanel use the context properties you're setting.