mixpanel-react-native 3.2.0-beta.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,22 +1,5 @@
1
1
  #
2
2
 
3
- ## [v3.2.0-beta.3](https://github.com/mixpanel/mixpanel-react-native/tree/v3.2.0-beta.3) (2025-12-15)
4
-
5
- ### Features
6
-
7
- - **Feature Flags**: Enable JavaScript mode support for Feature Flags
8
- - Full support for Expo and React Native Web
9
- - Runtime context updates via `updateContext()` (JavaScript mode only)
10
- - Complete parity with native implementation
11
- - Automatic fallback to JavaScript mode when native modules unavailable
12
- - AsyncStorage-based caching for offline support
13
-
14
- ### Improvements
15
-
16
- - Remove environment variable requirement for JavaScript mode flags
17
- - Enhanced documentation with Expo-specific examples
18
- - Improved test coverage for JavaScript mode
19
-
20
3
  ## [v3.1.3](https://github.com/mixpanel/mixpanel-react-native/tree/v3.1.3) (2025-12-15)
21
4
 
22
5
  ### Fixes
package/README.md CHANGED
@@ -47,7 +47,15 @@ Mixpanel's React Native SDK is a wrapper around Mixpanel’s native iOS and Andr
47
47
  npm install mixpanel-react-native
48
48
  ```
49
49
 
50
- 2. Under your application's ios folder, run
50
+ 2. Install AsyncStorage (required for data persistence):
51
+
52
+ ```
53
+ npm install @react-native-async-storage/async-storage
54
+ ```
55
+
56
+ > **Note:** Starting from v3.2.0, `@react-native-async-storage/async-storage` is a peer dependency. This allows your project to use either v1.x or v2.x, avoiding conflicts with frameworks like Expo 52+.
57
+
58
+ 3. Under your application's ios folder, run
51
59
 
52
60
  ```
53
61
  pod install
@@ -55,7 +63,7 @@ pod install
55
63
 
56
64
  Please note: You do not need to update your Podfile to add Mixpanel.
57
65
 
58
- 3. Since Xcode 12.5, there is a known swift compile issue, please refer to this **[workaround](https://github.com/mixpanel/mixpanel-react-native/issues/43#issuecomment-829599732)**. However the compile issue has been resolved in Xcode 13.2.1+, there is no extra step required as long as you upgrade to Xcode 13.2.1+.
66
+ 4. Since Xcode 12.5, there is a known swift compile issue, please refer to this **[workaround](https://github.com/mixpanel/mixpanel-react-native/issues/43#issuecomment-829599732)**. However the compile issue has been resolved in Xcode 13.2.1+, there is no extra step required as long as you upgrade to Xcode 13.2.1+.
59
67
 
60
68
  ### 2. Initialize Mixpanel
61
69
 
@@ -115,35 +123,6 @@ const SampleApp = () => {
115
123
  export default SampleApp;
116
124
  ```
117
125
 
118
- ### Feature Flags (Beta - 3.2.0-beta.1+)
119
-
120
- Control features dynamically and run A/B tests with Mixpanel Feature Flags. **Native mode only** (iOS/Android) in beta.
121
-
122
- #### Quick Start
123
-
124
- ```js
125
- // Enable during initialization
126
- await mixpanel.init(false, {}, 'https://api.mixpanel.com', true, {
127
- enabled: true,
128
- context: { platform: 'mobile' } // Optional targeting context
129
- });
130
-
131
- // Check if feature is enabled
132
- if (mixpanel.flags.areFlagsReady()) {
133
- const showNewUI = mixpanel.flags.isEnabledSync('new-feature', false);
134
- const buttonColor = mixpanel.flags.getVariantValueSync('button-color', 'blue');
135
- }
136
- ```
137
-
138
- #### Key Methods
139
-
140
- - `areFlagsReady()` - Check if flags are loaded
141
- - `isEnabledSync(name, fallback)` - Check if feature is enabled
142
- - `getVariantValueSync(name, fallback)` - Get variant value
143
- - `getVariantSync(name, fallback)` - Get full variant object with metadata
144
-
145
- All methods support async versions and snake_case aliases. See **[Feature Flags Quick Start Guide](FEATURE_FLAGS_QUICKSTART.md)** for complete documentation.
146
-
147
126
  ### Expo and React Native for Web support (3.0.2 and above)
148
127
 
149
128
  Starting from version 3.0.2, we have introduced support for Expo, React Native for Web, and other platforms utilizing React Native that do not support iOS and Android directly.
@@ -1,9 +1,6 @@
1
1
  package com.mixpanel.reactnative;
2
2
 
3
3
  import com.mixpanel.android.mpmetrics.MixpanelAPI;
4
- import com.mixpanel.android.mpmetrics.MixpanelOptions;
5
- import com.mixpanel.android.mpmetrics.MixpanelFlagVariant;
6
- import com.mixpanel.android.mpmetrics.FlagCompletionCallback;
7
4
 
8
5
  import com.facebook.react.bridge.Promise;
9
6
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -12,10 +9,6 @@ import com.facebook.react.bridge.ReactMethod;
12
9
  import com.facebook.react.bridge.ReadableArray;
13
10
  import com.facebook.react.bridge.ReadableMap;
14
11
  import com.facebook.react.bridge.Dynamic;
15
- import com.facebook.react.bridge.WritableMap;
16
- import com.facebook.react.bridge.WritableNativeMap;
17
- import com.facebook.react.bridge.WritableArray;
18
- import com.facebook.react.bridge.Callback;
19
12
 
20
13
  import org.json.JSONArray;
21
14
  import org.json.JSONException;
@@ -40,35 +33,10 @@ public class MixpanelReactNativeModule extends ReactContextBaseJavaModule {
40
33
 
41
34
 
42
35
  @ReactMethod
43
- public void initialize(String token, boolean trackAutomaticEvents, boolean optOutTrackingDefault, ReadableMap metadata, String serverURL, boolean useGzipCompression, ReadableMap featureFlagsOptions, Promise promise) throws JSONException {
36
+ public void initialize(String token, boolean trackAutomaticEvents, boolean optOutTrackingDefault, ReadableMap metadata, String serverURL, boolean useGzipCompression, Promise promise) throws JSONException {
44
37
  JSONObject mixpanelProperties = ReactNativeHelper.reactToJSON(metadata);
45
38
  AutomaticProperties.setAutomaticProperties(mixpanelProperties);
46
-
47
- // Handle feature flags options
48
- boolean featureFlagsEnabled = false;
49
- JSONObject featureFlagsContext = null;
50
-
51
- if (featureFlagsOptions != null && featureFlagsOptions.hasKey("enabled")) {
52
- featureFlagsEnabled = featureFlagsOptions.getBoolean("enabled");
53
-
54
- if (featureFlagsOptions.hasKey("context")) {
55
- featureFlagsContext = ReactNativeHelper.reactToJSON(featureFlagsOptions.getMap("context"));
56
- }
57
- }
58
-
59
- // Create Mixpanel instance with feature flags configuration
60
- MixpanelOptions.Builder optionsBuilder = new MixpanelOptions.Builder()
61
- .optOutTrackingDefault(optOutTrackingDefault)
62
- .superProperties(mixpanelProperties)
63
- .featureFlagsEnabled(featureFlagsEnabled);
64
-
65
- if (featureFlagsContext != null) {
66
- optionsBuilder.featureFlagsContext(featureFlagsContext);
67
- }
68
-
69
- MixpanelOptions options = optionsBuilder.build();
70
-
71
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, trackAutomaticEvents, options);
39
+ MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, optOutTrackingDefault, mixpanelProperties, null, trackAutomaticEvents);
72
40
  instance.setServerURL(serverURL);
73
41
  if (useGzipCompression) {
74
42
  instance.setShouldGzipRequestPayload(true);
@@ -634,242 +602,4 @@ public class MixpanelReactNativeModule extends ReactContextBaseJavaModule {
634
602
  promise.resolve(null);
635
603
  }
636
604
  }
637
-
638
- // Feature Flags Methods
639
-
640
- @ReactMethod
641
- public void loadFlags(final String token, Promise promise) {
642
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
643
- if (instance == null) {
644
- promise.reject("Instance Error", "Failed to get Mixpanel instance");
645
- return;
646
- }
647
- synchronized (instance) {
648
- instance.getFlags().loadFlags();
649
- promise.resolve(null);
650
- }
651
- }
652
-
653
- @ReactMethod(isBlockingSynchronousMethod = true)
654
- public boolean areFlagsReadySync(final String token) {
655
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
656
- if (instance == null) {
657
- return false;
658
- }
659
- synchronized (instance) {
660
- return instance.getFlags().areFlagsReady();
661
- }
662
- }
663
-
664
- @ReactMethod(isBlockingSynchronousMethod = true)
665
- public WritableMap getVariantSync(final String token, String featureName, ReadableMap fallback) {
666
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
667
- if (instance == null) {
668
- return convertVariantToMap(fallback);
669
- }
670
-
671
- synchronized (instance) {
672
- MixpanelFlagVariant fallbackVariant = convertMapToVariant(fallback);
673
- MixpanelFlagVariant variant = instance.getFlags().getVariantSync(featureName, fallbackVariant);
674
- return convertVariantToWritableMap(variant);
675
- }
676
- }
677
-
678
- // Note: For getVariantValueSync, we'll return the full variant and extract value in JS
679
- // React Native doesn't support returning Dynamic types from synchronous methods
680
- @ReactMethod(isBlockingSynchronousMethod = true)
681
- public WritableMap getVariantValueSync(final String token, String featureName, Dynamic fallbackValue) {
682
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
683
-
684
- WritableMap result = new WritableNativeMap();
685
- if (instance == null) {
686
- result.putString("type", "fallback");
687
- // We'll handle the conversion in JavaScript
688
- return result;
689
- }
690
-
691
- synchronized (instance) {
692
- Object value = instance.getFlags().getVariantValueSync(featureName, ReactNativeHelper.dynamicToObject(fallbackValue));
693
- result.putString("type", "value");
694
-
695
- // Convert value to appropriate type
696
- if (value == null) {
697
- result.putNull("value");
698
- } else if (value instanceof String) {
699
- result.putString("value", (String) value);
700
- } else if (value instanceof Boolean) {
701
- result.putBoolean("value", (Boolean) value);
702
- } else if (value instanceof Integer) {
703
- result.putInt("value", (Integer) value);
704
- } else if (value instanceof Double) {
705
- result.putDouble("value", (Double) value);
706
- } else if (value instanceof Float) {
707
- result.putDouble("value", ((Float) value).doubleValue());
708
- } else if (value instanceof Long) {
709
- result.putDouble("value", ((Long) value).doubleValue());
710
- } else {
711
- result.putString("value", value.toString());
712
- }
713
-
714
- return result;
715
- }
716
- }
717
-
718
- @ReactMethod(isBlockingSynchronousMethod = true)
719
- public boolean isEnabledSync(final String token, String featureName, boolean fallbackValue) {
720
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
721
- if (instance == null) {
722
- return fallbackValue;
723
- }
724
-
725
- synchronized (instance) {
726
- return instance.getFlags().isEnabledSync(featureName, fallbackValue);
727
- }
728
- }
729
-
730
- @ReactMethod
731
- public void getVariant(final String token, String featureName, ReadableMap fallback, final Promise promise) {
732
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
733
- if (instance == null) {
734
- promise.resolve(convertVariantToMap(fallback));
735
- return;
736
- }
737
-
738
- synchronized (instance) {
739
- MixpanelFlagVariant fallbackVariant = convertMapToVariant(fallback);
740
- instance.getFlags().getVariant(featureName, fallbackVariant, new FlagCompletionCallback<MixpanelFlagVariant>() {
741
- @Override
742
- public void onComplete(MixpanelFlagVariant variant) {
743
- promise.resolve(convertVariantToWritableMap(variant));
744
- }
745
- });
746
- }
747
- }
748
-
749
- @ReactMethod
750
- public void getVariantValue(final String token, String featureName, Dynamic fallbackValue, final Promise promise) {
751
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
752
- if (instance == null) {
753
- promise.resolve(fallbackValue);
754
- return;
755
- }
756
-
757
- synchronized (instance) {
758
- Object fallbackObj = ReactNativeHelper.dynamicToObject(fallbackValue);
759
- instance.getFlags().getVariantValue(featureName, fallbackObj, new FlagCompletionCallback<Object>() {
760
- @Override
761
- public void onComplete(Object value) {
762
- // Convert the value back to a format React Native can handle
763
- if (value == null) {
764
- promise.resolve(null);
765
- } else if (value instanceof String) {
766
- promise.resolve((String) value);
767
- } else if (value instanceof Boolean) {
768
- promise.resolve((Boolean) value);
769
- } else if (value instanceof Number) {
770
- promise.resolve(((Number) value).doubleValue());
771
- } else if (value instanceof JSONObject) {
772
- try {
773
- WritableMap map = ReactNativeHelper.convertJsonToMap((JSONObject) value);
774
- promise.resolve(map);
775
- } catch (Exception e) {
776
- promise.resolve(value.toString());
777
- }
778
- } else if (value instanceof JSONArray) {
779
- try {
780
- WritableArray array = ReactNativeHelper.convertJsonToArray((JSONArray) value);
781
- promise.resolve(array);
782
- } catch (Exception e) {
783
- promise.resolve(value.toString());
784
- }
785
- } else {
786
- promise.resolve(value.toString());
787
- }
788
- }
789
- });
790
- }
791
- }
792
-
793
- @ReactMethod
794
- public void isEnabled(final String token, String featureName, boolean fallbackValue, final Promise promise) {
795
- MixpanelAPI instance = MixpanelAPI.getInstance(this.mReactContext, token, true);
796
- if (instance == null) {
797
- promise.resolve(fallbackValue);
798
- return;
799
- }
800
-
801
- synchronized (instance) {
802
- instance.getFlags().isEnabled(featureName, fallbackValue, new FlagCompletionCallback<Boolean>() {
803
- @Override
804
- public void onComplete(Boolean isEnabled) {
805
- promise.resolve(isEnabled);
806
- }
807
- });
808
- }
809
- }
810
-
811
- // Helper methods for variant conversion
812
- private MixpanelFlagVariant convertMapToVariant(ReadableMap map) {
813
- if (map == null) {
814
- return new MixpanelFlagVariant("", null);
815
- }
816
-
817
- String key = map.hasKey("key") ? map.getString("key") : "";
818
- Object value = map.hasKey("value") ? ReactNativeHelper.dynamicToObject(map.getDynamic("value")) : null;
819
- String experimentID = map.hasKey("experimentID") ? map.getString("experimentID") : null;
820
- Boolean isExperimentActive = map.hasKey("isExperimentActive") ? map.getBoolean("isExperimentActive") : null;
821
- Boolean isQATester = map.hasKey("isQATester") ? map.getBoolean("isQATester") : null;
822
-
823
- // Create variant with all properties using the full constructor
824
- return new MixpanelFlagVariant(key, value, experimentID, isExperimentActive, isQATester);
825
- }
826
-
827
- private WritableMap convertVariantToMap(ReadableMap source) {
828
- WritableMap map = new WritableNativeMap();
829
- if (source != null) {
830
- map.merge(source);
831
- }
832
- return map;
833
- }
834
-
835
- private WritableMap convertVariantToWritableMap(MixpanelFlagVariant variant) {
836
- WritableMap map = new WritableNativeMap();
837
-
838
- if (variant != null) {
839
- map.putString("key", variant.key);
840
-
841
- Object value = variant.value;
842
- if (value == null) {
843
- map.putNull("value");
844
- } else if (value instanceof String) {
845
- map.putString("value", (String) value);
846
- } else if (value instanceof Boolean) {
847
- map.putBoolean("value", (Boolean) value);
848
- } else if (value instanceof Integer) {
849
- map.putInt("value", (Integer) value);
850
- } else if (value instanceof Double) {
851
- map.putDouble("value", (Double) value);
852
- } else if (value instanceof Float) {
853
- map.putDouble("value", ((Float) value).doubleValue());
854
- } else if (value instanceof Long) {
855
- map.putDouble("value", ((Long) value).doubleValue());
856
- } else {
857
- // For complex objects, convert to string
858
- map.putString("value", value.toString());
859
- }
860
-
861
- // Add optional fields if they exist
862
- if (variant.experimentID != null) {
863
- map.putString("experimentID", variant.experimentID);
864
- }
865
- if (variant.isExperimentActive != null) {
866
- map.putBoolean("isExperimentActive", variant.isExperimentActive);
867
- }
868
- if (variant.isQATester != null) {
869
- map.putBoolean("isQATester", variant.isQATester);
870
- }
871
- }
872
-
873
- return map;
874
- }
875
605
  }
package/index.d.ts CHANGED
@@ -7,69 +7,7 @@ export type MixpanelAsyncStorage = {
7
7
  removeItem(key: string): Promise<void>;
8
8
  };
9
9
 
10
- export interface MixpanelFlagVariant {
11
- key: string;
12
- value: any;
13
- experiment_id?: string | number; // Updated to match mixpanel-js format
14
- is_experiment_active?: boolean; // Updated to match mixpanel-js format
15
- is_qa_tester?: boolean; // Updated to match mixpanel-js format
16
- }
17
-
18
- export interface FeatureFlagsOptions {
19
- enabled?: boolean;
20
- context?: {
21
- [key: string]: any;
22
- custom_properties?: {
23
- [key: string]: any;
24
- };
25
- };
26
- }
27
-
28
- export interface UpdateContextOptions {
29
- replace?: boolean;
30
- }
31
-
32
- export interface Flags {
33
- // Synchronous methods
34
- loadFlags(): Promise<void>;
35
- areFlagsReady(): boolean;
36
- getVariantSync(featureName: string, fallback: MixpanelFlagVariant): MixpanelFlagVariant;
37
- getVariantValueSync(featureName: string, fallbackValue: any): any;
38
- isEnabledSync(featureName: string, fallbackValue?: boolean): boolean;
39
-
40
- // Asynchronous methods with overloads for callback and Promise patterns
41
- getVariant(featureName: string, fallback: MixpanelFlagVariant): Promise<MixpanelFlagVariant>;
42
- getVariant(featureName: string, fallback: MixpanelFlagVariant, callback: (result: MixpanelFlagVariant) => void): void;
43
-
44
- getVariantValue(featureName: string, fallbackValue: any): Promise<any>;
45
- getVariantValue(featureName: string, fallbackValue: any, callback: (value: any) => void): void;
46
-
47
- isEnabled(featureName: string, fallbackValue?: boolean): Promise<boolean>;
48
- isEnabled(featureName: string, fallbackValue: boolean, callback: (isEnabled: boolean) => void): void;
49
-
50
- // Context management (NEW - aligned with mixpanel-js)
51
- // NOTE: Only available in JavaScript mode (Expo/React Native Web)
52
- // In native mode, throws an error - context must be set during initialization
53
- updateContext(newContext: MixpanelProperties, options?: UpdateContextOptions): Promise<void>;
54
-
55
- // snake_case aliases (NEW - aligned with mixpanel-js)
56
- are_flags_ready(): boolean;
57
- get_variant(featureName: string, fallback: MixpanelFlagVariant): Promise<MixpanelFlagVariant>;
58
- get_variant(featureName: string, fallback: MixpanelFlagVariant, callback: (result: MixpanelFlagVariant) => void): void;
59
- get_variant_sync(featureName: string, fallback: MixpanelFlagVariant): MixpanelFlagVariant;
60
- get_variant_value(featureName: string, fallbackValue: any): Promise<any>;
61
- get_variant_value(featureName: string, fallbackValue: any, callback: (value: any) => void): void;
62
- get_variant_value_sync(featureName: string, fallbackValue: any): any;
63
- is_enabled(featureName: string, fallbackValue?: boolean): Promise<boolean>;
64
- is_enabled(featureName: string, fallbackValue: boolean, callback: (isEnabled: boolean) => void): void;
65
- is_enabled_sync(featureName: string, fallbackValue?: boolean): boolean;
66
- // NOTE: Only available in JavaScript mode (Expo/React Native Web)
67
- update_context(newContext: MixpanelProperties, options?: UpdateContextOptions): Promise<void>;
68
- }
69
-
70
10
  export class Mixpanel {
71
- readonly flags: Flags;
72
-
73
11
  constructor(token: string, trackAutoMaticEvents: boolean);
74
12
  constructor(token: string, trackAutoMaticEvents: boolean, useNative: true);
75
13
  constructor(
@@ -87,8 +25,7 @@ export class Mixpanel {
87
25
  optOutTrackingDefault?: boolean,
88
26
  superProperties?: MixpanelProperties,
89
27
  serverURL?: string,
90
- useGzipCompression?: boolean,
91
- featureFlagsOptions?: FeatureFlagsOptions
28
+ useGzipCompression?: boolean
92
29
  ): Promise<void>;
93
30
  setServerURL(serverURL: string): void;
94
31
  setLoggingEnabled(loggingEnabled: boolean): void;
package/index.js CHANGED
@@ -4,7 +4,6 @@ import {Platform, NativeModules} from "react-native";
4
4
  import packageJson from "./package.json";
5
5
  const {MixpanelReactNative} = NativeModules;
6
6
  import MixpanelMain from "mixpanel-react-native/javascript/mixpanel-main"
7
- import { MixpanelLogger } from "mixpanel-react-native/javascript/mixpanel-logger"
8
7
 
9
8
  const DevicePlatform = {
10
9
  Unknown: "Unknown",
@@ -47,8 +46,6 @@ export class Mixpanel {
47
46
  }
48
47
  this.token = token;
49
48
  this.trackAutomaticEvents = trackAutomaticEvents;
50
- this._flags = null; // Lazy-loaded flags instance
51
- this.storage = storage; // Store for JavaScript mode
52
49
 
53
50
  if (useNative && MixpanelReactNative) {
54
51
  this.mixpanelImpl = MixpanelReactNative;
@@ -63,117 +60,27 @@ export class Mixpanel {
63
60
  }
64
61
 
65
62
  /**
66
- * Returns the Flags instance for feature flags operations.
63
+ * Initializes Mixpanel
67
64
  *
68
- * <p>Feature Flags enable dynamic feature control and A/B testing capabilities.
69
- * This property is lazy-loaded to avoid unnecessary initialization until first access.
70
- *
71
- * <p><b>Native Mode Only:</b> Feature flags are currently only available when using native mode
72
- * (iOS/Android). JavaScript mode (Expo/React Native Web) support is planned for a future release.
73
- *
74
- * @return {Flags} an instance of Flags that provides access to feature flag operations
75
- * @throws {Error} if accessed in JavaScript mode (when native modules are not available)
76
- *
77
- * @example
78
- * // Check if flags are ready
79
- * if (mixpanel.flags.areFlagsReady()) {
80
- * const isEnabled = mixpanel.flags.isEnabledSync('new-checkout', false);
81
- * }
82
- *
83
- * @example
84
- * // Get a feature variant value
85
- * const buttonColor = mixpanel.flags.getVariantValueSync('button-color', 'blue');
86
- *
87
- * @see Flags
88
- */
89
- get flags() {
90
- if (!this._flags) {
91
- // Check if feature flags are enabled and warn if not
92
- if (!this.featureFlagsOptions || !this.featureFlagsOptions.enabled) {
93
- MixpanelLogger.warn(
94
- this.token,
95
- "Accessing feature flags API but flags are not enabled. " +
96
- "Call init() with featureFlagsOptions.enabled = true to enable feature flags. " +
97
- "Flag methods will return fallback values."
98
- );
99
- }
100
- // Lazy load the Flags instance with proper dependencies
101
- const Flags = require("./javascript/mixpanel-flags").Flags;
102
- this._flags = new Flags(this.token, this.mixpanelImpl, this.storage);
103
- }
104
- return this._flags;
105
- }
106
-
107
- /**
108
- * Initializes Mixpanel with optional configuration for tracking, super properties, and feature flags.
109
- *
110
- * <p>This method must be called before using any other Mixpanel functionality. It sets up
111
- * the tracking environment, registers super properties, and optionally initializes feature flags.
112
- *
113
- * @param {boolean} [optOutTrackingDefault=false] Whether or not Mixpanel can start tracking by default.
114
- * If true, no data will be tracked until optInTracking() is called. See optOutTracking()
115
- * @param {object} [superProperties={}] A Map containing the key value pairs of the super properties to register.
116
- * These properties will be sent with every event. Pass {} if no super properties needed.
117
- * @param {string} [serverURL="https://api.mixpanel.com"] The base URL used for Mixpanel API requests.
118
- * Use "https://api-eu.mixpanel.com" for EU data residency. See setServerURL()
119
- * @param {boolean} [useGzipCompression=false] Whether to use gzip compression for network requests.
120
- * Enabling this reduces bandwidth usage but adds slight CPU overhead.
121
- * @param {object} [featureFlagsOptions={}] Feature flags configuration object with the following properties:
122
- * @param {boolean} [featureFlagsOptions.enabled=false] Whether to enable feature flags functionality
123
- * @param {object} [featureFlagsOptions.context={}] Context properties used for feature flag targeting.
124
- * Can include user properties, device properties, or any custom properties for flag evaluation.
125
- * Note: In native mode, context must be set during initialization and cannot be updated later.
126
- * @returns {Promise<void>} A promise that resolves when initialization is complete
127
- *
128
- * @example
129
- * // Basic initialization
130
- * const mixpanel = new Mixpanel('YOUR_TOKEN', true);
131
- * await mixpanel.init();
132
- *
133
- * @example
134
- * // Initialize with feature flags enabled
135
- * const mixpanel = new Mixpanel('YOUR_TOKEN', true);
136
- * await mixpanel.init(false, {}, 'https://api.mixpanel.com', false, {
137
- * enabled: true,
138
- * context: {
139
- * platform: 'mobile',
140
- * app_version: '2.1.0'
141
- * }
142
- * });
143
- *
144
- * @example
145
- * // Initialize with EU data residency and super properties
146
- * await mixpanel.init(
147
- * false,
148
- * { plan: 'premium', region: 'eu' },
149
- * 'https://api-eu.mixpanel.com',
150
- * true
151
- * );
65
+ * @param {boolean} optOutTrackingDefault Optional Whether or not Mixpanel can start tracking by default. See optOutTracking()
66
+ * @param {object} superProperties Optional A Map containing the key value pairs of the super properties to register
67
+ * @param {string} serverURL Optional Set the base URL used for Mixpanel API requests. See setServerURL()
68
+ * @param {boolean} useGzipCompression Optional Set whether to use gzip compression for network requests. Defaults to false.
152
69
  */
153
70
  async init(
154
71
  optOutTrackingDefault = DEFAULT_OPT_OUT,
155
72
  superProperties = {},
156
73
  serverURL = "https://api.mixpanel.com",
157
- useGzipCompression = false,
158
- featureFlagsOptions = {}
74
+ useGzipCompression = false
159
75
  ) {
160
- // Store feature flags options for later use
161
- this.featureFlagsOptions = featureFlagsOptions;
162
-
163
76
  await this.mixpanelImpl.initialize(
164
77
  this.token,
165
78
  this.trackAutomaticEvents,
166
79
  optOutTrackingDefault,
167
80
  {...Helper.getMetaData(), ...superProperties},
168
81
  serverURL,
169
- useGzipCompression,
170
- featureFlagsOptions
82
+ useGzipCompression
171
83
  );
172
-
173
- // If flags are enabled AND we're in native mode, initialize them
174
- if (featureFlagsOptions.enabled && this.mixpanelImpl === MixpanelReactNative) {
175
- await this.flags.loadFlags();
176
- }
177
84
  }
178
85
 
179
86
  /**
@@ -202,9 +109,7 @@ export class Mixpanel {
202
109
  trackAutomaticEvents,
203
110
  optOutTrackingDefault,
204
111
  Helper.getMetaData(),
205
- "https://api.mixpanel.com",
206
- false,
207
- {}
112
+ "https://api.mixpanel.com"
208
113
  );
209
114
  return new Mixpanel(token, trackAutomaticEvents);
210
115
  }
@@ -5,7 +5,7 @@
5
5
 
6
6
  // MARK: - Mixpanel Instance
7
7
 
8
- RCT_EXTERN_METHOD(initialize:(NSString *)token trackAutomaticEvents:(BOOL)trackAutomaticEvents optOutTrackingByDefault:(BOOL)optOutTrackingByDefault properties:(NSDictionary *)properties serverURL:(NSString *)serverURL useGzipCompression:(BOOL)useGzipCompression featureFlagsOptions:(NSDictionary *)featureFlagsOptions resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
8
+ RCT_EXTERN_METHOD(initialize:(NSString *)token trackAutomaticEvents:(BOOL)trackAutomaticEvents optOutTrackingByDefault:(BOOL)optOutTrackingByDefault properties:(NSDictionary *)properties serverURL:(NSString *)serverURL useGzipCompression:(BOOL)useGzipCompression resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
9
9
 
10
10
  // Mark: - Settings
11
11
  RCT_EXTERN_METHOD(setServerURL:(NSString *)token serverURL:(NSString *)serverURL resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@@ -105,22 +105,4 @@ RCT_EXTERN_METHOD(groupRemovePropertyValue:(NSString *)token groupKey:(NSString
105
105
 
106
106
  RCT_EXTERN_METHOD(groupUnionProperty:(NSString *)token groupKey:(NSString *)groupKey groupID:(id)groupID name:(NSString *)name values:(NSArray *)values resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
107
107
 
108
- // MARK: - Feature Flags
109
-
110
- RCT_EXTERN_METHOD(loadFlags:(NSString *)token resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
111
-
112
- RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(areFlagsReadySync:(NSString *)token)
113
-
114
- RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(getVariantSync:(NSString *)token featureName:(NSString *)featureName fallback:(NSDictionary *)fallback)
115
-
116
- RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(getVariantValueSync:(NSString *)token featureName:(NSString *)featureName fallbackValue:(id)fallbackValue)
117
-
118
- RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(isEnabledSync:(NSString *)token featureName:(NSString *)featureName fallbackValue:(BOOL)fallbackValue)
119
-
120
- RCT_EXTERN_METHOD(getVariant:(NSString *)token featureName:(NSString *)featureName fallback:(NSDictionary *)fallback resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
121
-
122
- RCT_EXTERN_METHOD(getVariantValue:(NSString *)token featureName:(NSString *)featureName fallbackValue:(id)fallbackValue resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
123
-
124
- RCT_EXTERN_METHOD(isEnabled:(NSString *)token featureName:(NSString *)featureName fallbackValue:(BOOL)fallbackValue resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
125
-
126
108
  @end