Search code examples
iosreact-nativeexpoapp-storeapptrackingtransparency

Apple reviewers cannot see Tracking Transparency prompt implemented with expo-tracking-transparency


Even though I believe I have everything configured properly using expo-tracking-transparency 3.0.3 to prompt the user to accept or deny tracking, for some reason the Apple reviewer cannot see the prompt. But when I install the app on my phone, I can see it. I'm using the latest iOS 16.6.1 on our work iPhone.

This is Apple review response:

We're looking forward to completing our review, but we need more information to continue. Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 16.6.1.

Next Steps

Please explain where we can find the App Tracking Transparency permission request in your app. The request should appear before any data is collected that could be used to track the user.

If you've implemented App Tracking Transparency but the permission request is not appearing on devices running the latest OS, please review the available documentation and confirm App Tracking Transparency has been correctly implemented.

If your app does not track users, update your app privacy information in App Store Connect to not declare tracking. You must have the Account Holder or Admin role to update app privacy information.

I have implemented Google Google AdMob in my app using react-native-admob-native-ads 0.6.6

My app is build fully as an Expo SDK 48 managed project, so my whole app configuration is in app.config.js and app.json.

This is my configuration: app.config.js file is where all the app configuration is:

expo: {
    plugins: [
      "expo-localization",
      [
        "expo-build-properties",
        {
          ios: {
            useFrameworks: "static",
          },
        },
      ],
      [
        "expo-tracking-transparency",
        {
          userTrackingPermission:
            "This identifier will be used to deliver personalized ads to you.",
        },
      ],
    ],
  },

And I also have app.json file only with react-native-google-mobile-ads configuration, because this kind of configuration wasn't accepted in app.config.js file:

{
  "react-native-google-mobile-ads": {
    "android_app_id": "id-string",
    "ios_app_id": "id-string",
    "user_tracking_usage_description": "This identifier will be used to deliver personalized ads to you."
  }
}

In the app.tsx file I have an useEffect hook that initialize the prompt:

  React.useEffect(() => {
    ;(async () => {
      try {
        await TrackingTransparency.requestTrackingPermissionsAsync()
      } catch (error) {
        console.error({
          msg: "Error requesting tracking permissions",
          error,
        })
      }
    })()
  }, [])

The ad is served using the NativeAdView component from react-native-admob-native-ads package:

const nativeAdId = Platform.OS === "ios" ? Config.NATIVE_AD_ID_IOS : Config.NATIVE_AD_ID_ANDROID

<NativeAdView
  style={$cardItem}
  ref={nativeAdViewRef}
  adUnitID={nativeAdId}
  targetingOptions={{ keywords }}
  onNativeAdLoaded={onAdLoaded}
  adChoicesPlacement="topRight"
  requestNonPersonalizedAdsOnly={true}
  >
   <NativeMediaView
      muted={true}
      paused={false}
      onVideoPlay={() => console.log("playing")}
      style={$mediaContent}
     />
</NativeAdView>

I really don't understand why the prompt wouldn't show for the Apple reviewers. I'm not sure how the Apple is reviewing the apps, but for example I have seen that if I install my app via TestFlight, this prompt doesn't show, but if I build the app for preview with Expo, and download it to my phone, the prompt show every time when the app is freshly installed.

I also sent a video to the reviewer to show how the prompt is showed on my device, but that didn't help.

I'm completely clueless how to solve this issue, and I'll appreciate help. Just, I don't have any iOS nor Android configuration in my project, everything is Expo managed.


Solution

  • Try this solution:

    After finding this answer, where Apple's documentation says that it should be placed in the applicationDidBecomeActive, it seems like the issue is that the app isn't active.

    My fix was to add a timeout around the request to wait until the application is loaded:

    setTimeout(async () => {
      const { granted } = await requestTrackingPermissionsAsync();
    }, 500);
    

    Another option is to add an event listener and see when the application is active through Expo App State and call it then.