expo-facebook-analytics 1.0.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.
Files changed (46) hide show
  1. package/README.md +242 -0
  2. package/android/build.gradle +60 -0
  3. package/android/src/main/java/com/nitrofbanalytics/HybridFacebookAnalytics.kt +139 -0
  4. package/app.plugin.js +1 -0
  5. package/expo-facebook-analytics.podspec +31 -0
  6. package/ios/HybridFacebookAnalytics.swift +135 -0
  7. package/lib/index.d.ts +58 -0
  8. package/lib/index.js +138 -0
  9. package/lib/specs/FacebookAnalytics.nitro.d.ts +20 -0
  10. package/lib/specs/FacebookAnalytics.nitro.js +2 -0
  11. package/lib/types.d.ts +65 -0
  12. package/lib/types.js +52 -0
  13. package/nitro.json +19 -0
  14. package/nitrogen/generated/.gitattributes +1 -0
  15. package/nitrogen/generated/android/NitroFBAnalytics+autolinking.cmake +81 -0
  16. package/nitrogen/generated/android/NitroFBAnalytics+autolinking.gradle +27 -0
  17. package/nitrogen/generated/android/NitroFBAnalyticsOnLoad.cpp +44 -0
  18. package/nitrogen/generated/android/NitroFBAnalyticsOnLoad.hpp +25 -0
  19. package/nitrogen/generated/android/c++/JHybridFacebookAnalyticsSpec.cpp +157 -0
  20. package/nitrogen/generated/android/c++/JHybridFacebookAnalyticsSpec.hpp +79 -0
  21. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitrofbanalytics/HybridFacebookAnalyticsSpec.kt +110 -0
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitrofbanalytics/NitroFBAnalyticsOnLoad.kt +35 -0
  23. package/nitrogen/generated/ios/NitroFBAnalytics+autolinking.rb +60 -0
  24. package/nitrogen/generated/ios/NitroFBAnalytics-Swift-Cxx-Bridge.cpp +49 -0
  25. package/nitrogen/generated/ios/NitroFBAnalytics-Swift-Cxx-Bridge.hpp +171 -0
  26. package/nitrogen/generated/ios/NitroFBAnalytics-Swift-Cxx-Umbrella.hpp +47 -0
  27. package/nitrogen/generated/ios/NitroFBAnalyticsAutolinking.mm +33 -0
  28. package/nitrogen/generated/ios/NitroFBAnalyticsAutolinking.swift +26 -0
  29. package/nitrogen/generated/ios/c++/HybridFacebookAnalyticsSpecSwift.cpp +11 -0
  30. package/nitrogen/generated/ios/c++/HybridFacebookAnalyticsSpecSwift.hpp +167 -0
  31. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  32. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +54 -0
  33. package/nitrogen/generated/ios/swift/HybridFacebookAnalyticsSpec.swift +69 -0
  34. package/nitrogen/generated/ios/swift/HybridFacebookAnalyticsSpec_cxx.swift +410 -0
  35. package/nitrogen/generated/shared/c++/HybridFacebookAnalyticsSpec.cpp +34 -0
  36. package/nitrogen/generated/shared/c++/HybridFacebookAnalyticsSpec.hpp +78 -0
  37. package/package.json +66 -0
  38. package/plugin/build/index.d.ts +13 -0
  39. package/plugin/build/index.js +42 -0
  40. package/plugin/build/withFacebookAnalyticsAndroid.d.ts +14 -0
  41. package/plugin/build/withFacebookAnalyticsAndroid.js +67 -0
  42. package/plugin/build/withFacebookAnalyticsIOS.d.ts +16 -0
  43. package/plugin/build/withFacebookAnalyticsIOS.js +96 -0
  44. package/src/index.ts +161 -0
  45. package/src/specs/FacebookAnalytics.nitro.ts +47 -0
  46. package/src/types.ts +67 -0
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withAndroidPermissions = exports.withFacebookManifest = exports.withFacebookAppIdString = void 0;
4
+ const config_plugins_1 = require("@expo/config-plugins");
5
+ const withFacebookAppIdString = (config, props) => {
6
+ return (0, config_plugins_1.withStringsXml)(config, (mod) => {
7
+ const stringItems = mod.modResults.resources.string ?? [];
8
+ const setString = (name, value) => {
9
+ const existing = stringItems.findIndex((item) => item.$.name === name);
10
+ const entry = {
11
+ $: { name, translatable: "false" },
12
+ _: value,
13
+ };
14
+ if (existing >= 0) {
15
+ stringItems[existing] = entry;
16
+ }
17
+ else {
18
+ stringItems.push(entry);
19
+ }
20
+ };
21
+ setString("facebook_app_id", props.appID);
22
+ setString("facebook_client_token", props.clientToken);
23
+ setString("facebook_login_protocol_scheme", props.scheme);
24
+ mod.modResults.resources.string = stringItems;
25
+ return mod;
26
+ });
27
+ };
28
+ exports.withFacebookAppIdString = withFacebookAppIdString;
29
+ const withFacebookManifest = (config, props) => {
30
+ return (0, config_plugins_1.withAndroidManifest)(config, (mod) => {
31
+ const mainApplication = config_plugins_1.AndroidConfig.Manifest.getMainApplicationOrThrow(mod.modResults);
32
+ // Add meta-data entries
33
+ if (!mainApplication["meta-data"]) {
34
+ mainApplication["meta-data"] = [];
35
+ }
36
+ const metaData = mainApplication["meta-data"];
37
+ const setMetaData = (name, value) => {
38
+ const existing = metaData.findIndex((item) => item.$["android:name"] === name);
39
+ const entry = {
40
+ $: {
41
+ "android:name": name,
42
+ "android:value": value,
43
+ },
44
+ };
45
+ if (existing >= 0) {
46
+ metaData[existing] = entry;
47
+ }
48
+ else {
49
+ metaData.push(entry);
50
+ }
51
+ };
52
+ setMetaData("com.facebook.sdk.ApplicationId", "@string/facebook_app_id");
53
+ setMetaData("com.facebook.sdk.ClientToken", "@string/facebook_client_token");
54
+ setMetaData("com.facebook.sdk.ApplicationName", props.displayName);
55
+ setMetaData("com.facebook.sdk.AutoInitEnabled", String(props.isAutoInitEnabled));
56
+ setMetaData("com.facebook.sdk.AutoLogAppEventsEnabled", String(props.autoLogAppEventsEnabled));
57
+ setMetaData("com.facebook.sdk.AdvertiserIDCollectionEnabled", String(props.advertiserIDCollectionEnabled));
58
+ return mod;
59
+ });
60
+ };
61
+ exports.withFacebookManifest = withFacebookManifest;
62
+ const withAndroidPermissions = (config, _props) => {
63
+ return config_plugins_1.AndroidConfig.Permissions.withPermissions(config, [
64
+ "android.permission.INTERNET",
65
+ ]);
66
+ };
67
+ exports.withAndroidPermissions = withAndroidPermissions;
@@ -0,0 +1,16 @@
1
+ import { type ConfigPlugin } from "@expo/config-plugins";
2
+ type ResolvedProps = {
3
+ appID: string;
4
+ clientToken: string;
5
+ displayName: string;
6
+ scheme: string;
7
+ isAutoInitEnabled: boolean;
8
+ autoLogAppEventsEnabled: boolean;
9
+ advertiserIDCollectionEnabled: boolean;
10
+ iosUserTrackingPermission?: string | false;
11
+ };
12
+ export declare const withFacebookIOS: ConfigPlugin<ResolvedProps>;
13
+ export declare const withUserTrackingPermission: ConfigPlugin<ResolvedProps>;
14
+ export declare const withFacebookAppDelegate: ConfigPlugin<ResolvedProps>;
15
+ export declare const withSKAdNetworkIdentifiers: ConfigPlugin<string[]>;
16
+ export {};
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withSKAdNetworkIdentifiers = exports.withFacebookAppDelegate = exports.withUserTrackingPermission = exports.withFacebookIOS = void 0;
4
+ const config_plugins_1 = require("@expo/config-plugins");
5
+ const withFacebookIOS = (config, props) => {
6
+ return (0, config_plugins_1.withInfoPlist)(config, (mod) => {
7
+ mod.modResults.FacebookAppID = props.appID;
8
+ mod.modResults.FacebookClientToken = props.clientToken;
9
+ mod.modResults.FacebookDisplayName = props.displayName;
10
+ mod.modResults.FacebookAutoInitEnabled = props.isAutoInitEnabled;
11
+ mod.modResults.FacebookAutoLogAppEventsEnabled =
12
+ props.autoLogAppEventsEnabled;
13
+ mod.modResults.FacebookAdvertiserIDCollectionEnabled =
14
+ props.advertiserIDCollectionEnabled;
15
+ // URL schemes
16
+ if (!mod.modResults.CFBundleURLTypes) {
17
+ mod.modResults.CFBundleURLTypes = [];
18
+ }
19
+ const fbSchemeEntry = mod.modResults.CFBundleURLTypes.find((entry) => entry.CFBundleURLSchemes?.includes(props.scheme));
20
+ if (!fbSchemeEntry) {
21
+ mod.modResults.CFBundleURLTypes.push({
22
+ CFBundleURLSchemes: [props.scheme],
23
+ });
24
+ }
25
+ // LSApplicationQueriesSchemes
26
+ const queriesSchemes = [
27
+ "fbapi",
28
+ "fb-messenger-api",
29
+ "fbauth2",
30
+ "fbshareextension",
31
+ ];
32
+ if (!mod.modResults.LSApplicationQueriesSchemes) {
33
+ mod.modResults.LSApplicationQueriesSchemes = [];
34
+ }
35
+ for (const scheme of queriesSchemes) {
36
+ if (!mod.modResults.LSApplicationQueriesSchemes.includes(scheme)) {
37
+ mod.modResults.LSApplicationQueriesSchemes.push(scheme);
38
+ }
39
+ }
40
+ return mod;
41
+ });
42
+ };
43
+ exports.withFacebookIOS = withFacebookIOS;
44
+ const withUserTrackingPermission = (config, props) => {
45
+ if (props.iosUserTrackingPermission === false) {
46
+ return config;
47
+ }
48
+ return (0, config_plugins_1.withInfoPlist)(config, (mod) => {
49
+ mod.modResults.NSUserTrackingUsageDescription =
50
+ props.iosUserTrackingPermission ||
51
+ "This identifier will be used to deliver personalized ads to you.";
52
+ return mod;
53
+ });
54
+ };
55
+ exports.withUserTrackingPermission = withUserTrackingPermission;
56
+ const withFacebookAppDelegate = (config, _props) => {
57
+ return (0, config_plugins_1.withAppDelegate)(config, (mod) => {
58
+ const contents = mod.modResults.contents;
59
+ // Add import
60
+ if (!contents.includes("#import <FBSDKCoreKit/FBSDKCoreKit.h>")) {
61
+ mod.modResults.contents = mod.modResults.contents.replace('#import "AppDelegate.h"', '#import "AppDelegate.h"\n#import <FBSDKCoreKit/FBSDKCoreKit.h>');
62
+ }
63
+ // Add didFinishLaunchingWithOptions hook
64
+ if (!contents.includes("FBSDKApplicationDelegate")) {
65
+ mod.modResults.contents = mod.modResults.contents.replace("self.initialProps = @{};", "self.initialProps = @{};\n [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];");
66
+ }
67
+ // Add openURL handler
68
+ if (!contents.includes("openURL:url options:options")) {
69
+ const openURLMethod = `
70
+
71
+ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
72
+ return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options];
73
+ }`;
74
+ mod.modResults.contents = mod.modResults.contents.replace(/@end\s*$/, `${openURLMethod}\n\n@end\n`);
75
+ }
76
+ return mod;
77
+ });
78
+ };
79
+ exports.withFacebookAppDelegate = withFacebookAppDelegate;
80
+ const withSKAdNetworkIdentifiers = (config, identifiers) => {
81
+ return (0, config_plugins_1.withInfoPlist)(config, (mod) => {
82
+ if (!mod.modResults.SKAdNetworkItems) {
83
+ mod.modResults.SKAdNetworkItems = [];
84
+ }
85
+ const existing = new Set(mod.modResults.SKAdNetworkItems.map((item) => item.SKAdNetworkIdentifier));
86
+ for (const id of identifiers) {
87
+ if (!existing.has(id)) {
88
+ mod.modResults.SKAdNetworkItems.push({
89
+ SKAdNetworkIdentifier: id,
90
+ });
91
+ }
92
+ }
93
+ return mod;
94
+ });
95
+ };
96
+ exports.withSKAdNetworkIdentifiers = withSKAdNetworkIdentifiers;
package/src/index.ts ADDED
@@ -0,0 +1,161 @@
1
+ import { NitroModules } from "react-native-nitro-modules";
2
+ import type { FacebookAnalytics as FacebookAnalyticsSpec } from "./specs/FacebookAnalytics.nitro";
3
+ import type { AppEventsFlushBehavior, Params, UserData } from "./types";
4
+
5
+ export type { AppEventsFlushBehavior, Params, UserData } from "./types";
6
+ export { AppEventParams, AppEvents } from "./types";
7
+
8
+ const NativeFBAnalytics =
9
+ NitroModules.createHybridObject<FacebookAnalyticsSpec>("FacebookAnalytics");
10
+
11
+ /**
12
+ * Log a custom or predefined app event.
13
+ * @param eventName - Event name (use AppEvents constants for predefined events)
14
+ * @param args - Optional valueToSum (number) and/or params object
15
+ */
16
+ export function logEvent(
17
+ eventName: string,
18
+ ...args: Array<number | Params>
19
+ ): void {
20
+ let valueToSum = 0;
21
+ let params: Params = {};
22
+
23
+ for (const arg of args) {
24
+ if (typeof arg === "number") {
25
+ valueToSum = arg;
26
+ } else if (typeof arg === "object") {
27
+ params = arg;
28
+ }
29
+ }
30
+
31
+ const stringParams: Record<string, string> = {};
32
+ for (const [key, value] of Object.entries(params)) {
33
+ stringParams[key] = String(value);
34
+ }
35
+
36
+ if (Object.keys(stringParams).length > 0) {
37
+ NativeFBAnalytics.logEvent(eventName, valueToSum, stringParams);
38
+ } else {
39
+ NativeFBAnalytics.logEventWithoutParams(eventName, valueToSum);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Log a purchase event.
45
+ */
46
+ export function logPurchase(
47
+ purchaseAmount: number,
48
+ currencyCode: string,
49
+ parameters?: Params,
50
+ ): void {
51
+ const stringParams: Record<string, string> = {};
52
+ if (parameters) {
53
+ for (const [key, value] of Object.entries(parameters)) {
54
+ stringParams[key] = String(value);
55
+ }
56
+ }
57
+ NativeFBAnalytics.logPurchase(purchaseAmount, currencyCode, stringParams);
58
+ }
59
+
60
+ /**
61
+ * Log a push notification open event.
62
+ */
63
+ export function logPushNotificationOpen(
64
+ payload?: Record<string, string | number>,
65
+ ): void {
66
+ const stringPayload: Record<string, string> = {};
67
+ if (payload) {
68
+ for (const [key, value] of Object.entries(payload)) {
69
+ stringPayload[key] = String(value);
70
+ }
71
+ }
72
+ NativeFBAnalytics.logPushNotificationOpen(stringPayload);
73
+ }
74
+
75
+ /**
76
+ * Set the user ID for analytics association.
77
+ */
78
+ export function setUserID(userID: string | null): void {
79
+ if (userID === null) {
80
+ NativeFBAnalytics.clearUserID();
81
+ } else {
82
+ NativeFBAnalytics.setUserID(userID);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Clear the current user ID.
88
+ */
89
+ export function clearUserID(): void {
90
+ NativeFBAnalytics.clearUserID();
91
+ }
92
+
93
+ /**
94
+ * Get the current user ID.
95
+ */
96
+ export function getUserID(): string | undefined {
97
+ return NativeFBAnalytics.getUserID();
98
+ }
99
+
100
+ /**
101
+ * Set user data for advanced matching.
102
+ */
103
+ export function setUserData(userData: UserData): void {
104
+ NativeFBAnalytics.setUserData(
105
+ userData.email,
106
+ userData.firstName,
107
+ userData.lastName,
108
+ userData.phone,
109
+ userData.dateOfBirth,
110
+ userData.gender,
111
+ userData.city,
112
+ userData.state,
113
+ userData.zip,
114
+ userData.country,
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Get the anonymous device ID.
120
+ */
121
+ export function getAnonymousID(): Promise<string | undefined> {
122
+ return NativeFBAnalytics.getAnonymousID();
123
+ }
124
+
125
+ /**
126
+ * Get the advertiser ID (IDFA on iOS, AAID on Android).
127
+ */
128
+ export function getAdvertiserID(): Promise<string | undefined> {
129
+ return NativeFBAnalytics.getAdvertiserID();
130
+ }
131
+
132
+ /**
133
+ * Set the flush behavior for event batching.
134
+ * @param flushBehavior - 'auto' or 'explicit_only'
135
+ */
136
+ export function setFlushBehavior(flushBehavior: AppEventsFlushBehavior): void {
137
+ NativeFBAnalytics.setFlushBehavior(flushBehavior);
138
+ }
139
+
140
+ /**
141
+ * Flush all queued events to Facebook immediately.
142
+ */
143
+ export function flush(): void {
144
+ NativeFBAnalytics.flush();
145
+ }
146
+
147
+ /**
148
+ * Set the push notification device token (iOS).
149
+ */
150
+ export function setPushNotificationsDeviceToken(deviceToken: string): void {
151
+ NativeFBAnalytics.setPushNotificationsDeviceToken(deviceToken);
152
+ }
153
+
154
+ /**
155
+ * Set the push notification registration ID (Android/FCM).
156
+ */
157
+ export function setPushNotificationsRegistrationId(
158
+ registrationId: string,
159
+ ): void {
160
+ NativeFBAnalytics.setPushNotificationsRegistrationId(registrationId);
161
+ }
@@ -0,0 +1,47 @@
1
+ import type { HybridObject } from "react-native-nitro-modules";
2
+
3
+ export interface FacebookAnalytics
4
+ extends HybridObject<{ ios: "swift"; android: "kotlin" }> {
5
+ // Event logging
6
+ logEvent(
7
+ eventName: string,
8
+ valueToSum: number,
9
+ params: Record<string, string>,
10
+ ): void;
11
+ logEventWithoutParams(eventName: string, valueToSum: number): void;
12
+ logPurchase(
13
+ amount: number,
14
+ currency: string,
15
+ params: Record<string, string>,
16
+ ): void;
17
+ logPushNotificationOpen(payload: Record<string, string>): void;
18
+
19
+ // User identity
20
+ setUserID(userID: string): void;
21
+ clearUserID(): void;
22
+ getUserID(): string | undefined;
23
+ setUserData(
24
+ email: string | undefined,
25
+ firstName: string | undefined,
26
+ lastName: string | undefined,
27
+ phone: string | undefined,
28
+ dateOfBirth: string | undefined,
29
+ gender: string | undefined,
30
+ city: string | undefined,
31
+ state: string | undefined,
32
+ zip: string | undefined,
33
+ country: string | undefined,
34
+ ): void;
35
+
36
+ // Device identifiers
37
+ getAnonymousID(): Promise<string | undefined>;
38
+ getAdvertiserID(): Promise<string | undefined>;
39
+
40
+ // Configuration
41
+ setFlushBehavior(flushBehavior: string): void;
42
+ flush(): void;
43
+
44
+ // Push notification tokens
45
+ setPushNotificationsDeviceToken(token: string): void;
46
+ setPushNotificationsRegistrationId(registrationId: string): void;
47
+ }
package/src/types.ts ADDED
@@ -0,0 +1,67 @@
1
+ export type AppEventsFlushBehavior = "auto" | "explicit_only";
2
+
3
+ export type Params = { [key: string]: string | number };
4
+
5
+ export type UserData = Readonly<{
6
+ email?: string;
7
+ firstName?: string;
8
+ lastName?: string;
9
+ phone?: string;
10
+ dateOfBirth?: string;
11
+ gender?: "m" | "f";
12
+ city?: string;
13
+ state?: string;
14
+ zip?: string;
15
+ country?: string;
16
+ }>;
17
+
18
+ /**
19
+ * Predefined Facebook App Event names.
20
+ */
21
+ export const AppEvents = {
22
+ AchievedLevel: "fb_mobile_level_achieved",
23
+ AdClick: "AdClick",
24
+ AdImpression: "AdImpression",
25
+ AddedPaymentInfo: "fb_mobile_add_payment_info",
26
+ AddedToCart: "fb_mobile_add_to_cart",
27
+ AddedToWishlist: "fb_mobile_add_to_wishlist",
28
+ CompletedRegistration: "fb_mobile_complete_registration",
29
+ CompletedTutorial: "fb_mobile_tutorial_completion",
30
+ Contact: "Contact",
31
+ CustomizeProduct: "CustomizeProduct",
32
+ Donate: "Donate",
33
+ FindLocation: "FindLocation",
34
+ InitiatedCheckout: "fb_mobile_initiated_checkout",
35
+ Purchased: "fb_mobile_purchase",
36
+ Rated: "fb_mobile_rate",
37
+ Searched: "fb_mobile_search",
38
+ SpentCredits: "fb_mobile_spent_credits",
39
+ Schedule: "Schedule",
40
+ StartTrial: "StartTrial",
41
+ SubmitApplication: "SubmitApplication",
42
+ Subscribe: "Subscribe",
43
+ UnlockedAchievement: "fb_mobile_achievement_unlocked",
44
+ ViewedContent: "fb_mobile_content_view",
45
+ } as const;
46
+
47
+ /**
48
+ * Predefined Facebook App Event parameter names.
49
+ */
50
+ export const AppEventParams = {
51
+ AddType: "fb_mobile_add_type",
52
+ Content: "fb_content",
53
+ ContentID: "fb_content_id",
54
+ ContentType: "fb_content_type",
55
+ Currency: "fb_currency",
56
+ Description: "fb_description",
57
+ Level: "fb_level",
58
+ NumItems: "fb_num_items",
59
+ MaxRatingValue: "fb_max_rating_value",
60
+ OrderId: "fb_order_id",
61
+ PaymentInfoAvailable: "fb_payment_info_available",
62
+ RegistrationMethod: "fb_registration_method",
63
+ SearchString: "fb_search_string",
64
+ Success: "fb_success",
65
+ ValueNo: "0",
66
+ ValueYes: "1",
67
+ } as const;