DocsTracking MethodsSDKsiOS (Swift)OpenFeature Provider (Swift)

OpenFeature Provider (Swift)

Overview

This guide covers using Mixpanel’s Feature Flags through the OpenFeature 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) 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

Installation

Add the following to your Package.swift:

dependencies: [
    .package(url: "https://github.com/mixpanel/mixpanel-swift-openfeature", from: "0.1.0"),
]

Then add MixpanelOpenFeature as a dependency of your target:

.target(
    name: "YourTarget",
    dependencies: [
        .product(name: "MixpanelOpenFeature", package: "mixpanel-swift-openfeature"),
    ]
),

Quick Start

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

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 for targeting, call these methods on the same Mixpanel instance that was passed to the provider.

// 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 TypeVariant ValuesOpenFeature Method
Feature Gatetrue / falsegetBooleanValue()
Experimentboolean, string, number, or JSON objectgetBooleanValue(), getStringValue(), getIntegerValue(), getDoubleValue(), or getObjectValue()
Dynamic ConfigJSON objectgetObjectValue()
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():

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 targeting:

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

let details = client.getBooleanDetails(key: "my-feature", defaultValue: false)
 
print(details.value)
print(details.variant)
print(details.reason)
print(details.errorCode)

Error Handling

Error CodeWhen
PROVIDER_NOT_READYFlags evaluated before the provider has finished initializing
FLAG_NOT_FOUNDThe requested flag does not exist in Mixpanel
TYPE_MISMATCHThe flag value type does not match the requested type

To avoid PROVIDER_NOT_READY, use setProviderAndWait:

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:

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.

Was this page useful?