Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/analytics/usage/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,31 @@ of your app handle data in a way that requires ATT)

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

# Google Analytics on-device conversion measurement

If you would like to enable Google Analytics on-device conversion measurement APIs on iOS, define the following variable in your Podfile:

```ruby
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
```

During `pod install`, using that variable adds the `GoogleAdsOnDeviceConversion` Pod.

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:

```json
[
"@react-native-firebase/analytics",
{
"ios": {
"googleAppMeasurementOnDeviceConversion": true
}
}
]
```

This adds `$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true` to the generated iOS `Podfile` during prebuild.

# Device Identification

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`.
Expand Down
7 changes: 4 additions & 3 deletions docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,21 @@ The following is an example `app.json` to enable the React Native Firebase modul

> 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`).

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

```json
[
"@react-native-firebase/analytics",
{
"ios": {
"withoutAdIdSupport": true
"withoutAdIdSupport": true,
"googleAppMeasurementOnDeviceConversion": true
}
}
]
```

This adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` to the generated iOS `Podfile` during prebuild.
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.

### Local app compilation

Expand Down
7 changes: 4 additions & 3 deletions packages/analytics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ yarn add @react-native-firebase/analytics

### Expo

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

```json
{
Expand All @@ -50,7 +50,8 @@ If you use Expo, including EAS Build, and want to build iOS Analytics without Ad
"@react-native-firebase/analytics",
{
"ios": {
"withoutAdIdSupport": true
"withoutAdIdSupport": true,
"googleAppMeasurementOnDeviceConversion": true
}
}
]
Expand All @@ -59,7 +60,7 @@ If you use Expo, including EAS Build, and want to build iOS Analytics without Ad
}
```

This adds `$RNFirebaseAnalyticsWithoutAdIdSupport = true` to the generated iOS `Podfile` during prebuild, which excludes `FirebaseAnalytics/IdentitySupport`.
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.

## Documentation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`Analytics Config Plugin iOS Tests adds both iOS Podfile flags when both analytics options are enabled 1`] = `
"platform :ios, '15.0'

prepare_react_native_project!
# @generated begin @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion - expo prebuild (DO NOT MODIFY) sync-6d1952a1f7b9ccb2d313cbd66659db4cdeae591f
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
# @generated end @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion
# @generated begin @react-native-firebase/analytics-withoutAdIdSupport - expo prebuild (DO NOT MODIFY) sync-06c0e725ab83bc834a9294f76fea47cf14bb6ac3
$RNFirebaseAnalyticsWithoutAdIdSupport = true
# @generated end @react-native-firebase/analytics-withoutAdIdSupport

target 'ReactNativeFirebaseDemo' do
end
"
`;

exports[`Analytics Config Plugin iOS Tests adds the Podfile flag when googleAppMeasurementOnDeviceConversion is enabled 1`] = `
"platform :ios, '15.0'

prepare_react_native_project!
# @generated begin @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion - expo prebuild (DO NOT MODIFY) sync-6d1952a1f7b9ccb2d313cbd66659db4cdeae591f
$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true
# @generated end @react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion

target 'ReactNativeFirebaseDemo' do
end
"
`;

exports[`Analytics Config Plugin iOS Tests adds the Podfile flag when withoutAdIdSupport is enabled 1`] = `
"platform :ios, '15.0'

Expand Down
43 changes: 42 additions & 1 deletion packages/analytics/plugin/__tests__/iosPlugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { describe, expect, it } from '@jest/globals';

import { setAnalyticsPodfileWithoutAdIdSupport } from '../src/ios/podfile';
import {
setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion,
setAnalyticsPodfileWithoutAdIdSupport,
} from '../src/ios/podfile';

const podfileFixture = `platform :ios, '15.0'

Expand Down Expand Up @@ -29,4 +32,42 @@ describe('Analytics Config Plugin iOS Tests', function () {

expect(restored).toEqual(podfileFixture);
});

it('adds the Podfile flag when googleAppMeasurementOnDeviceConversion is enabled', function () {
const result = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(podfileFixture, true);
expect(result).toMatchSnapshot();
});

it('is idempotent when the ODM Podfile flag is already present', function () {
const onceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
podfileFixture,
true,
);
const twiceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
onceModified,
true,
);

expect(twiceModified).toEqual(onceModified);
});

it('removes the generated Podfile flag when googleAppMeasurementOnDeviceConversion is disabled', function () {
const onceModified = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
podfileFixture,
true,
);
const restored = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(onceModified, false);

expect(restored).toEqual(podfileFixture);
});

it('adds both iOS Podfile flags when both analytics options are enabled', function () {
const withWithoutAdIdSupport = setAnalyticsPodfileWithoutAdIdSupport(podfileFixture, true);
const result = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
withWithoutAdIdSupport,
true,
);

expect(result).toMatchSnapshot();
});
});
3 changes: 2 additions & 1 deletion packages/analytics/plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins';

import { withIosWithoutAdIdSupport } from './ios';
import { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion } from './ios';
import { PluginConfigType } from './pluginConfig';

/**
Expand All @@ -10,6 +10,7 @@ const withRnFirebaseAnalytics: ConfigPlugin<PluginConfigType> = (config, props)
return withPlugins(config, [
// iOS
[withIosWithoutAdIdSupport, props],
[withIosGoogleAppMeasurementOnDeviceConversion, props],
]);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/analytics/plugin/src/ios/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { withIosWithoutAdIdSupport } from './podfile';
import { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion } from './podfile';

export { withIosWithoutAdIdSupport };
export { withIosWithoutAdIdSupport, withIosGoogleAppMeasurementOnDeviceConversion };
40 changes: 36 additions & 4 deletions packages/analytics/plugin/src/ios/podfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,57 @@ import { PluginConfigType } from '../pluginConfig';
const TAG = '@react-native-firebase/analytics-withoutAdIdSupport';
const ANCHOR = /prepare_react_native_project!/;
const FLAG = '$RNFirebaseAnalyticsWithoutAdIdSupport = true';
const TAG_ODM = '@react-native-firebase/analytics-googleAppMeasurementOnDeviceConversion';
const FLAG_ODM = '$RNFirebaseAnalyticsGoogleAppMeasurementOnDeviceConversion = true';

export function setAnalyticsPodfileWithoutAdIdSupport(
function setAnalyticsPodfileFlag(
src: string,
tag: string,
flag: string,
enabled: boolean = false,
): string {
if (!enabled) {
return removeGeneratedContents(src, TAG) ?? src;
return removeGeneratedContents(src, tag) ?? src;
}

return mergeContents({
src,
newSrc: FLAG,
tag: TAG,
newSrc: flag,
tag,
anchor: ANCHOR,
offset: 1,
comment: '#',
}).contents;
}

export function setAnalyticsPodfileWithoutAdIdSupport(
src: string,
enabled: boolean = false,
): string {
return setAnalyticsPodfileFlag(src, TAG, FLAG, enabled);
}

export function setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
src: string,
enabled: boolean = false,
): string {
return setAnalyticsPodfileFlag(src, TAG_ODM, FLAG_ODM, enabled);
}

export const withIosGoogleAppMeasurementOnDeviceConversion: ConfigPlugin<PluginConfigType> = (
config,
props,
) => {
return withPodfile(config, config => {
config.modResults.contents = setAnalyticsPodfileGoogleAppMeasurementOnDeviceConversion(
config.modResults.contents,
props?.ios?.googleAppMeasurementOnDeviceConversion === true,
);

return config;
});
};

export const withIosWithoutAdIdSupport: ConfigPlugin<PluginConfigType> = (config, props) => {
return withPodfile(config, config => {
config.modResults.contents = setAnalyticsPodfileWithoutAdIdSupport(
Expand Down
4 changes: 4 additions & 0 deletions packages/analytics/plugin/src/pluginConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ export interface PluginConfigType {

export interface PluginConfigTypeIos {
withoutAdIdSupport?: boolean;
/**
* @platform ios iOS
*/
googleAppMeasurementOnDeviceConversion?: boolean;
}
Loading