Skip to content

Commit 6edab6f

Browse files
sokoloff06russellwheatleymikehardy
authored
feat(analytics): add support for googleAppMeasurementOnDeviceConversion in iOS Expo plugin (#9014)
--------- Co-authored-by: russellwheatley <russellwheatley85@gmail.com> Co-authored-by: Mike Hardy <github@mikehardy.net>
1 parent 72d4e89 commit 6edab6f

9 files changed

Lines changed: 148 additions & 14 deletions

File tree

docs/analytics/usage/index.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,31 @@ of your app handle data in a way that requires ATT)
171171

172172
Note that for obvious reasons, configuring Firebase Analytics for use without IDFA is incompatible with AdMob
173173

174+
# Google Analytics on-device conversion measurement
175+
176+
If you would like to enable Google Analytics on-device conversion measurement APIs on iOS, define the following variable in your Podfile:
177+
178+
```ruby
179+
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
180+
```
181+
182+
During `pod install`, using that variable adds the `GoogleAdsOnDeviceConversion` Pod.
183+
184+
If you use Expo, including EAS Build, add the Analytics config plugin to your `app.json` / `app.config.js` instead of editing the generated Podfile manually:
185+
186+
```json
187+
[
188+
"@react-native-firebase/analytics",
189+
{
190+
"ios": {
191+
"googleAppMeasurementOnDeviceConversion": true
192+
}
193+
}
194+
]
195+
```
196+
197+
This adds `$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true` to the generated iOS `Podfile` during prebuild.
198+
174199
# Device Identification
175200

176201
If you would like to enable Firebase Analytics to generate automatic audience metrics for iOS (as it does by default in Android), you must link additional iOS libraries, [as documented by the Google Firebase team](https://support.google.com/firebase/answer/6318039). Specifically you need to link in `AdSupport.framework`.

docs/index.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,21 @@ The following is an example `app.json` to enable the React Native Firebase modul
7878

7979
> Listing a module in the Config Plugins (the `"plugins"` array in the JSON above) is only required for React Native Firebase modules that involve _native installation steps_ - e.g. modifying the Xcode project, `Podfile`, `build.gradle`, `AndroidManifest.xml` etc. React Native Firebase modules without native steps will work out of the box; no `"plugins"` entry is required. Not all modules have Expo Config Plugins provided yet. A React Native Firebase module has Config Plugin support if it contains an `app.plugin.js` file in its package directory (e.g.`node_modules/@react-native-firebase/app/app.plugin.js`).
8080
81-
If you use `@react-native-firebase/analytics` with Expo, including EAS Build, and want to opt out of iOS Ad ID support, add the Analytics config plugin with the `withoutAdIdSupport` iOS option:
81+
If you use `@react-native-firebase/analytics` with Expo, including EAS Build, and want to configure iOS Analytics Podfile flags, add the Analytics config plugin with the relevant iOS options:
8282

8383
```json
8484
[
8585
"@react-native-firebase/analytics",
8686
{
8787
"ios": {
88-
"withoutAdIdSupport": true
88+
"withoutAdIdSupport": true,
89+
"googleAppMeasurementOnDeviceConversion": true
8990
}
9091
}
9192
]
9293
```
9394

94-
This adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` to the generated iOS `Podfile` during prebuild.
95+
The `withoutAdIdSupport` option adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` to opt out of iOS Ad ID support. The `googleAppMeasurementOnDeviceConversion` option adds `$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true` to include Google Analytics on-device conversion measurement support. You may omit either option if it is not needed.
9596

9697
### Local app compilation
9798

packages/analytics/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ yarn add @react-native-firebase/analytics
4040

4141
### Expo
4242

43-
If you use Expo, including EAS Build, and want to build iOS Analytics without Ad ID support, add the Analytics config plugin to your `app.json` / `app.config.js`:
43+
If you use Expo, including EAS Build, and want to configure iOS Analytics Podfile flags, add the Analytics config plugin to your `app.json` / `app.config.js`:
4444

4545
```json
4646
{
@@ -50,7 +50,8 @@ If you use Expo, including EAS Build, and want to build iOS Analytics without Ad
5050
"@react-native-firebase/analytics",
5151
{
5252
"ios": {
53-
"withoutAdIdSupport": true
53+
"withoutAdIdSupport": true,
54+
"googleAppMeasurementOnDeviceConversion": true
5455
}
5556
}
5657
]
@@ -59,7 +60,7 @@ If you use Expo, including EAS Build, and want to build iOS Analytics without Ad
5960
}
6061
```
6162

62-
This adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` to the generated iOS `Podfile` during prebuild, which excludes `FirebaseAnalytics/IdentitySupport`.
63+
The `withoutAdIdSupport` option adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` during prebuild, which excludes `FirebaseAnalytics/IdentitySupport`. The `googleAppMeasurementOnDeviceConversion` option adds `$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true`, which includes Google Analytics on-device conversion measurement support. You may omit either option if it is not needed.
6364

6465
## Documentation
6566

packages/analytics/plugin/__tests__/__snapshots__/iosPlugin.test.ts.snap

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

3+
exports[`Analytics Config Plugin iOS Tests adds both iOS Podfile flags when both analytics options are enabled 1`] = `
4+
"platform :ios, '15.0'
5+
6+
prepare_react_native_project!
7+
# @generated begin @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion - expo prebuild (DO NOT MODIFY) sync-6d1952a1f7b9ccb2d313cbd66659db4cdeae591f
8+
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
9+
# @generated end @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion
10+
# @generated begin @react-native-firebase/analytics-withoutAdIdSupport - expo prebuild (DO NOT MODIFY) sync-06c0e725ab83bc834a9294f76fea47cf14bb6ac3
11+
$RNFirebaseAnalyticsWithoutAdIdSupport = true
12+
# @generated end @react-native-firebase/analytics-withoutAdIdSupport
13+
14+
target 'ReactNativeFirebaseDemo' do
15+
end
16+
"
17+
`;
18+
19+
exports[`Analytics Config Plugin iOS Tests adds the Podfile flag when googleAppMeasurementOnDeviceConversion is enabled 1`] = `
20+
"platform :ios, '15.0'
21+
22+
prepare_react_native_project!
23+
# @generated begin @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion - expo prebuild (DO NOT MODIFY) sync-6d1952a1f7b9ccb2d313cbd66659db4cdeae591f
24+
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
25+
# @generated end @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion
26+
27+
target 'ReactNativeFirebaseDemo' do
28+
end
29+
"
30+
`;
31+
332
exports[`Analytics Config Plugin iOS Tests adds the Podfile flag when withoutAdIdSupport is enabled 1`] = `
433
"platform :ios, '15.0'
534

packages/analytics/plugin/__tests__/iosPlugin.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { describe, expect, it } from '@jest/globals';
22

3-
import { setAnalyticsPodfileWithoutAdIdSupport } from '../src/ios/podfile';
3+
import {
4+
setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion,
5+
setAnalyticsPodfileWithoutAdIdSupport,
6+
} from '../src/ios/podfile';
47

58
const podfileFixture = `platform :ios, '15.0'
69
@@ -29,4 +32,42 @@ describe('Analytics Config Plugin iOS Tests', function () {
2932

3033
expect(restored).toEqual(podfileFixture);
3134
});
35+
36+
it('adds the Podfile flag when googleAppMeasurementOnDeviceConversion is enabled', function () {
37+
const result = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(podfileFixture, true);
38+
expect(result).toMatchSnapshot();
39+
});
40+
41+
it('is idempotent when the ODM Podfile flag is already present', function () {
42+
const onceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
43+
podfileFixture,
44+
true,
45+
);
46+
const twiceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
47+
onceModified,
48+
true,
49+
);
50+
51+
expect(twiceModified).toEqual(onceModified);
52+
});
53+
54+
it('removes the generated Podfile flag when googleAppMeasurementOnDeviceConversion is disabled', function () {
55+
const onceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
56+
podfileFixture,
57+
true,
58+
);
59+
const restored = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(onceModified, false);
60+
61+
expect(restored).toEqual(podfileFixture);
62+
});
63+
64+
it('adds both iOS Podfile flags when both analytics options are enabled', function () {
65+
const withWithoutAdIdSupport = setAnalyticsPodfileWithoutAdIdSupport(podfileFixture, true);
66+
const result = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
67+
withWithoutAdIdSupport,
68+
true,
69+
);
70+
71+
expect(result).toMatchSnapshot();
72+
});
3273
});

packages/analytics/plugin/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins';
22

3-
import { withIosWithoutAdIdSupport } from './ios';
3+
import { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion } from './ios';
44
import { PluginConfigType } from './pluginConfig';
55

66
/**
@@ -10,6 +10,7 @@ const withRnFirebaseAnalytics: ConfigPlugin<PluginConfigType> = (config, props)
1010
return withPlugins(config, [
1111
// iOS
1212
[withIosWithoutAdIdSupport, props],
13+
[withIosGoogleAppMeasurementOnDeviceConversion, props],
1314
]);
1415
};
1516

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { withIosWithoutAdIdSupport } from './podfile';
1+
import { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion } from './podfile';
22

3-
export { withIosWithoutAdIdSupport };
3+
export { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion };

packages/analytics/plugin/src/ios/podfile.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,57 @@ import { PluginConfigType } from '../pluginConfig';
99
const TAG = '@react-native-firebase/analytics-withoutAdIdSupport';
1010
const ANCHOR = /prepare_react_native_project!/;
1111
const FLAG = '$RNFirebaseAnalyticsWithoutAdIdSupport = true';
12+
const TAG_ODM = '@react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion';
13+
const FLAG_ODM = '$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true';
1214

13-
export function setAnalyticsPodfileWithoutAdIdSupport(
15+
function setAnalyticsPodfileFlag(
1416
src: string,
17+
tag: string,
18+
flag: string,
1519
enabled: boolean = false,
1620
): string {
1721
if (!enabled) {
18-
return removeGeneratedContents(src, TAG) ?? src;
22+
return removeGeneratedContents(src, tag) ?? src;
1923
}
2024

2125
return mergeContents({
2226
src,
23-
newSrc: FLAG,
24-
tag: TAG,
27+
newSrc: flag,
28+
tag,
2529
anchor: ANCHOR,
2630
offset: 1,
2731
comment: '#',
2832
}).contents;
2933
}
3034

35+
export function setAnalyticsPodfileWithoutAdIdSupport(
36+
src: string,
37+
enabled: boolean = false,
38+
): string {
39+
return setAnalyticsPodfileFlag(src, TAG, FLAG, enabled);
40+
}
41+
42+
export function setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
43+
src: string,
44+
enabled: boolean = false,
45+
): string {
46+
return setAnalyticsPodfileFlag(src, TAG_ODM, FLAG_ODM, enabled);
47+
}
48+
49+
export const withIosGoogleAppMeasurementOnDeviceConversion: ConfigPlugin<PluginConfigType> = (
50+
config,
51+
props,
52+
) => {
53+
return withPodfile(config, config => {
54+
config.modResults.contents = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
55+
config.modResults.contents,
56+
props?.ios?.googleAppMeasurementOnDeviceConversion === true,
57+
);
58+
59+
return config;
60+
});
61+
};
62+
3163
export const withIosWithoutAdIdSupport: ConfigPlugin<PluginConfigType> = (config, props) => {
3264
return withPodfile(config, config => {
3365
config.modResults.contents = setAnalyticsPodfileWithoutAdIdSupport(

packages/analytics/plugin/src/pluginConfig.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ export interface PluginConfigType {
44

55
export interface PluginConfigTypeIos {
66
withoutAdIdSupport?: boolean;
7+
/**
8+
* @platform ios iOS
9+
*/
10+
googleAppMeasurementOnDeviceConversion?: boolean;
711
}

0 commit comments

Comments
 (0)