Quantcast
Channel: Active questions tagged react-native+ios - Stack Overflow
Viewing all articles
Browse latest Browse all 17158

React Native App Stopped Logging Conversions to Google Ads

$
0
0

I have a React Native Expo app for iOS that uses Firebase and Firebase Analytics to log user installs. The app correctly logs events to Firebase and Firebase Analytics, where I can see events such as first_open and session_start. This Firebase project is connected to my Google Ads account, where I run app install ads. I can see new users in Google Analytics, but these installs are not reflected in Google Ads.

The last logged event was on July 12th. Since then, no app download/install events have been recorded in Google Ads.

Here's what I've done so far:

Ensured Firebase is correctly linked to Google Ads in the project settings/integrations.Confirmed that events are properly logging in Google Analytics and the Firebase console.Set events as key events in Firebase.Ensured conversions are active in Google Ads.I also tried adding the AdSupport framework to my app using a script from this GitHub post, but I'm not sure if it succeeded. After this update, there seems to be an issue with first_open reporting to Firebase.

I am certain that the events displayed in analytics originate from Google Ads and not from the App Store. This is because the app is new and has very low visibility in the App Store. Additionally, when I disable the ads, no new users are acquired.

Did anyone had experience with problem like this and if yes did you solve it and how?

My app configuration:

app.json:

{"expo": {"name": "******","slug": "******","version": "1.3.12","orientation": "portrait","icon": "./assets/images/icon.png","scheme": "******","userInterfaceStyle": "automatic","facebookAppId": "******","facebookDisplayName": "******","facebookScheme": "fb******","splash": {"image": "./assets/images/splash.png","resizeMode": "contain","backgroundColor": "#ffffff"    },"ios": {"supportsTablet": true,"bundleIdentifier": "******","appStoreUrl": "https://apps.apple.com/app/id******","googleServicesFile": "./GoogleService-Info.plist","infoPlist": {"NSAppTransportSecurity": {"NSAllowsArbitraryLoads": true        },"UIBackgroundModes": ["fetch", "remote-notification"],"FirebaseAppDelegateProxyEnabled": true,"AppsFlyerAppID": "******","FacebookClientToken": "******","NSUserTrackingUsageDescription": "This identifier will help us understand how you found us. No other data will be collected."      },"entitlements": {"aps-environment": "production"      },"buildNumber": "1"    },"android": {"versionCode": 1,"googleServicesFile": "./google-services.json","permissions": ["INTERNET", "com.android.vending.BILLING", "ACCESS_NETWORK_STATE", "ACCESS_WIFI_STATE", "WAKE_LOCK", "RECEIVE_BOOT_COMPLETED"],"adaptiveIcon": {"foregroundImage": "./assets/images/adaptive-icon.png","backgroundColor": "#ffffff"      },"package": "******"    },"web": {"bundler": "metro","output": "static","favicon": "./assets/images/favicon.png"    },"plugins": ["expo-router","@react-native-firebase/app","@react-native-firebase/messaging","@react-native-firebase/crashlytics","./plugins/withPodfile",      ["expo-build-properties",        {"ios": {"useFrameworks": "static","extraPodspecs": ["pod 'AdSupport', '>= 1.0'"]          },"android": {"permissions": ["com.android.vending.BILLING"]          }        }      ],"expo-font",      ["react-native-fbsdk-next",        {"appID": "******","clientToken": "******","displayName": "******","scheme": "fb******","advertiserIDCollectionEnabled": true,"autoLogAppEventsEnabled": true,"isAutoInitEnabled": true,"iosUserTrackingPermission": "This identifier will help us understand how you found us. No other data will be collected."        }      ]    ],"experiments": {"typedRoutes": true    },"extra": {"router": {"origin": false      },"eas": {"projectId": "******","env": "production"      }    }  }}

eas.json:

{"cli": {"version": ">= 9.0.5","appVersionSource": "remote"  },"build": {"development": {"developmentClient": true,"distribution": "internal"    },"preview": {"distribution": "internal","channel": "preview"    },"production": {"channel": "production","autoIncrement": true,"android": {"buildType": "app-bundle"      }    }  },"submit": {"production": {}  }}

GoogleService-Info.plist:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>API_KEY</key><string>******</string><key>GCM_SENDER_ID</key><string>******</string><key>PLIST_VERSION</key><string>1</string><key>BUNDLE_ID</key><string>******</string><key>PROJECT_ID</key><string>******</string><key>STORAGE_BUCKET</key><string>******</string><key>IS_ADS_ENABLED</key><true/><key>IS_ANALYTICS_ENABLED</key><true/><key>IS_APPINVITE_ENABLED</key><true/><key>IS_GCM_ENABLED</key><true/><key>IS_SIGNIN_ENABLED</key><true/><key>GOOGLE_APP_ID</key><string>******</string></dict></plist>

google-services.json:

{"project_info": {"project_number": "******","project_id": "******","storage_bucket": "******"  },"client": [    {"client_info": {"mobilesdk_app_id": "******","android_client_info": {"package_name": "******"        }      },"oauth_client": [],"api_key": [        {"current_key": "******"        }      ],"services": {"appinvite_service": {"other_platform_oauth_client": []        }      }    }  ],"configuration_version": "1"}

package.json:

{"name": "******","main": "expo-router/entry","version": "1.0.0","scripts": {"start": "expo start","android": "expo run:android","ios": "expo run:ios","web": "expo start --web","test": "jest --watchAll","copy": "node ./scripts/copy-config.js","clean": "node ./scripts/clean-config.js","setversion": "node ./scripts/setversion.js",  },"jest": {"preset": "jest-expo"  },"dependencies": {"@expo/config-plugins": "~8.0.5","@expo/dev-server": "0.5.5","@expo/metro-config": "^0.18.7","@expo/vector-icons": "^14.0.2","@react-native-async-storage/async-storage": "^1.23.1","@react-native-firebase/analytics": "^20.1.0","@react-native-firebase/app": "^20.1.0","@react-native-firebase/crashlytics": "^20.1.0","@react-native-firebase/messaging": "^20.1.0","@react-navigation/native": "^6.1.17","@sentry/react-native": "^5.24.1","axios": "^1.7.2","babel-plugin-module-resolver": "^5.0.2","date-fns": "^3.6.0","dotenv": "^16.4.5","eas": "^0.1.0","expo": "51.0.14","expo-build-properties": "~0.12.3","expo-constants": "~16.0.2","expo-dev-client": "~4.0.18","expo-device": "~6.0.2","expo-font": "~12.0.7","expo-linear-gradient": "~13.0.2","expo-linking": "~6.3.1","expo-notifications": "~0.28.9","expo-router": "~3.5.16","expo-splash-screen": "~0.27.5","expo-status-bar": "~1.12.1","expo-store-review": "~7.0.2","expo-system-ui": "~3.0.6","expo-tracking-transparency": "~4.0.2","expo-updates": "~0.25.17","expo-web-browser": "~13.0.3","install": "^0.13.0","jest-expo": "~51.0.2","react": "18.2.0","react-dom": "18.2.0","react-native": "0.74.2","react-native-branch": "^6.2.2","react-native-fbsdk-next": "^13.0.0","react-native-get-random-values": "^1.11.0","react-native-glassfy-module": "^1.6.2","react-native-global-props": "^1.1.5","react-native-reanimated-carousel": "^3.5.1","react-native-safe-area-context": "4.10.5","react-native-screens": "3.32.0","react-native-svg": "^15.3.0","react-native-swiper": "^1.6.0","react-native-ux-cam": "^5.4.16","react-native-web": "~0.19.12","styled-components": "^6.1.11","uuid": "^10.0.0","with-google-idfa-support": "^0.1.0"  },"devDependencies": {"@babel/core": "^7.24.7","@types/react": "~18.3.3","@types/react-native-global-props": "^1.1.6","@types/react-native-vector-icons": "^6.4.18","@types/uuid": "^10.0.0","jest": "^29.7.0","jest-expo": "~51.0.2","metro-react-native-babel-preset": "^0.77.0","react-test-renderer": "18.2.0","typescript": "~5.5.2"  },"private": true}

layout.tsx:

import 'react-native-get-random-values';import { v4 as uuidv4 } from 'uuid';import React, { useEffect, useState } from 'react';import { StatusBar } from 'react-native';import * as SplashScreen from 'expo-splash-screen';import { ThemeProvider, DefaultTheme } from '@react-navigation/native';import { useFonts } from 'expo-font';import { Stack } from 'expo-router';import FontAwesome from '@expo/vector-icons/FontAwesome';import { AppProvider, useAppContext } from '@contexts/AppContext';import { setCustomText } from 'react-native-global-props';import { GlassfyProvider, useGlassfy } from './contexts/GlassfyContext';import Constants from 'expo-constants';import Strings from '@root/constants/strings';import { getFcmToken } from './utils/permissionUtils';import * as Sentry from '@sentry/react-native';import { DetailedStatsProvider } from './contexts/DetailedStatsContext';import { SnapshotProvider } from './contexts/SnapShotContext';import { createUser, updateNotificationLogClicked, createAttribution } from './api/Questions';import { getData, storeData } from './utils/asyncStorage';import { getUUID } from './utils/uuId';import * as Linking from 'expo-linking';import * as Notifications from 'expo-notifications';import RNUxcam from 'react-native-ux-cam';let messaging: typeof import('@react-native-firebase/messaging').default | undefined;let firebase: typeof import('@react-native-firebase/app').default | undefined;let AppEventsLogger: typeof import('react-native-fbsdk-next').AppEventsLogger | undefined;let Settings: typeof import('react-native-fbsdk-next').Settings | undefined;let requestTrackingPermissionsAsync: typeof import('expo-tracking-transparency').requestTrackingPermissionsAsync | undefined;let analytics: typeof import('@react-native-firebase/analytics').default | undefined;const isProduction = Constants.expoConfig?.extra?.eas?.env === 'production';if (isProduction) {  messaging = require('@react-native-firebase/messaging').default;  firebase = require('@react-native-firebase/app').default;  AppEventsLogger = require('react-native-fbsdk-next').AppEventsLogger;  Settings = require('react-native-fbsdk-next').Settings;  requestTrackingPermissionsAsync = require('expo-tracking-transparency').requestTrackingPermissionsAsync;  analytics = require('@react-native-firebase/analytics').default;  Sentry.init({    dsn: Strings.SENTRY_DSN,    enableSpotlight: __DEV__,  });  const originalConsoleError = console.error;  console.error = (...args) => {    Sentry.captureException(new Error(args.join(" ")));    originalConsoleError(...args);  };}SplashScreen.preventAutoHideAsync();const linking = {  prefixes: [Strings.LINKING_PREFIX],  config: {    screens: {      PaymentScreen: '/PaymentScreen',      Home: '/(tabs)',    },  },};export default function RootComponent() {  const [fontsLoaded] = useFonts({    FontThin: require('@assets/fonts/Lato/Lato-Thin.ttf'),    FontLight: require('@assets/fonts/Lato/Lato-Light.ttf'),    FontRegular: require('@assets/fonts/Lato/Lato-Regular.ttf'),    FontSemiBold: require('@assets/fonts/Lato/Lato-Bold.ttf'),    FontBold: require('@assets/fonts/Lato/Lato-Bold.ttf'),    ...FontAwesome.font,  });  const [isFacebookInitialized, setIsFacebookInitialized] = useState(false);  const [isEventLogged, setIsEventLogged] = useState(false);  const [isUxCamInitialized, setIsUxCamInitialized] = useState(false);  const [isAnalyticsLoaded, setIsAnalyticsLoaded] = useState(false);  useEffect(() => {    if (isProduction) {      try {        const initizeUxCam = () => {          if (isUxCamInitialized) return;          try {            RNUxcam?.optIntoSchematicRecordings();            const configuration = {              userAppKey: Strings.UXCAM_APP_KEY,              enableAutomaticScreenNameTagging: false,              enableImprovedScreenCapture: true,            };            RNUxcam?.startWithConfiguration(configuration);            setIsUxCamInitialized(true);            Sentry.addBreadcrumb({              category: 'uxcam',              message: 'UXCam initialized successfully',              level: 'info',            });          } catch (initError) {            console.error("Error initializing UXCam:", initError);            Sentry.captureException(initError);          }        };        const registerUxcam = async () => {          try {            const device_uuid = await getUUID();            if (RNUxcam) {              RNUxcam.setUserIdentity(device_uuid);              Sentry.addBreadcrumb({                category: 'uxcam',                message: 'UXCam user identity set successfully',                level: 'info',              });            } else {              const error = new Error("RNUxcam is undefined");              console.error("Error setting RNUxcam Identity, RNUXcam is undefined");              Sentry.captureException(error);            }          } catch (error) {            console.error("Error setting RNUxcam Identity, device_id: ", error);            Sentry.captureException(error);          }        };        initizeUxCam();        console.log("UxCam Init True");        Sentry.addBreadcrumb({          category: 'uxcam',          message: 'Calling registerUxcam function',          level: 'info',        });        registerUxcam();      } catch (error) {        console.error("UxCam Init Error", error);        Sentry.captureException(error);      }    }  }, [isUxCamInitialized, isProduction, RNUxcam]);  useEffect(() => {    if (isProduction) {      try {        const initializeAnalytics = async () => {          if (isAnalyticsLoaded) return;          await analytics?.().setAnalyticsCollectionEnabled(true);          setIsAnalyticsLoaded(true);          console.log("Firebase Analytics Initialized");        };        initializeAnalytics();      } catch (error) {        console.error("Firebase Analytics Init Error", error);      }    }  }, [isAnalyticsLoaded, isProduction]);  useEffect(() => {    async function initialize() {      try {      } catch (error) {        console.error('Initialization error:', error);      } finally {        if (fontsLoaded) {          await SplashScreen.hideAsync();          console.log('Splash screen hidden');        }      }    }    if (fontsLoaded) {      initialize();    }  }, [fontsLoaded, isProduction]);  useEffect(() => {    if (isProduction) {      async function initializeFacebookSDK() {        if (isFacebookInitialized) return;        try {          Settings?.initializeSDK();          setIsFacebookInitialized(true);        } catch (error) {          console.error('Facebook SDK initialization error:', error);        }        if (!isEventLogged) {          try {            AppEventsLogger?.logEvent('fb_mobile_activate_app');            setIsEventLogged(true);          } catch (error) {            console.error('Error logging Facebook event:', error);          }        }      }      async function registerUser() {        try {          console.log("Starting registerUser function...");          const device_uuid = await getUUID();          console.log("Device UUID retrieved:", device_uuid);          const onBoardingFinished = await getData('onboardingFinished');          console.log("Onboarding status retrieved:", onBoardingFinished);          if (device_uuid) {            const otherTracking = "";            console.log("Calling createUser API with device_uuid:", device_uuid, "and otherTracking:", otherTracking);            const user = await createUser(device_uuid, otherTracking);            console.log('User created:', user);            try {              Sentry.setUser({                id: device_uuid,              });            } catch (error) {              console.error("Error setting Sentry User device_id: ", device_uuid, "Error: ", error);            }            try {              if (analytics) {                await analytics().setUserId(device_uuid);              } else {                console.error("Error setting Firebase Analytics user, Firebase Analytics is undefined");              }            } catch (error) {              console.error("Error setting Firebase Analytics User, device_id:", device_uuid, "Error:", error);            }          }          try {            if (onBoardingFinished === 'true') {              await getFcmToken();            }          } catch (err) {            console.error('Error getting FCM token:', err);          }        } catch (error) {          console.error('Error registering user:', error);        }      }      registerUser();      initializeFacebookSDK();    }  }, [isFacebookInitialized, isEventLogged, isProduction,]);  if (!fontsLoaded) {    return null;  }  const customTextProps = {    style: {      fontFamily: 'FontLight',      fontSize: 14,      lineHeight: 14,    },  };  setCustomText(customTextProps);  return (<AppProvider><GlassfyProvider><DetailedStatsProvider><SnapshotProvider><App /></SnapshotProvider></DetailedStatsProvider></GlassfyProvider></AppProvider>  );}const App = () => {  const { subscription, setSubscription, setIsNotificationLink } = useAppContext();  const { checkActiveSubscription } = useGlassfy();  useEffect(() => {    const checkSubscriptionStatus = async () => {      try {        const isActive = await checkActiveSubscription();        setSubscription(isActive);        console.log('Subscription status checked:', isActive);      } catch (error) {        console.error('Error checking subscription status:', error);      }    };    checkSubscriptionStatus();  }, [subscription, checkActiveSubscription]);  useEffect(() => {    Notifications.addNotificationResponseReceivedListener(response => {      console.log('Notification received:', JSON.stringify(response)); // Log the entire notification object      const trigger = response.notification.request.trigger as Notifications.PushNotificationTrigger;      const url: string | undefined = trigger?.payload?.link as string | undefined;      const notificationLogId: string | undefined = trigger?.payload?.notificationLogId as string | undefined;      const adminSubscription: string | undefined = trigger?.payload?.adminSubscription as string | undefined;      if (url) {        setIsNotificationLink(true);        Linking.openURL(url).catch(err => {          console.error('Failed to open URL:', err);        });      } else {        console.error('No URL found in notification data');      }      if (notificationLogId) {        updateNotificationLogClicked(parseInt(notificationLogId), true)          .then(() => {            console.log(`Notification log ${notificationLogId} marked as clicked.`);          })          .catch(error => {            console.error(`Error updating notification log ${notificationLogId}:`, error);          });      } else {        console.log('No notification log ID found in notification data');      }      if (adminSubscription) {        storeData("adminSubscription", adminSubscription);      } else {        console.log('No adminSubscription has been found in notification data');      }    });    const getInitialURL = async () => {      try {        const initialURL = await Linking.getInitialURL();        if (initialURL) {          setIsNotificationLink(true);          Linking.openURL(initialURL).catch(err => {            console.error('Failed to open initial URL:', err);          });        }      } catch (error) {        console.error('Failed to get initial URL:', error);      }    };    getInitialURL();  }, [setIsNotificationLink]);  return (<><StatusBar        barStyle="dark-content"        translucent={true}        backgroundColor="transparent"      /><RootLayoutNav /></>  );};function RootLayoutNav() {  return (<ThemeProvider value={DefaultTheme}><Stack screenOptions={{ headerShown: false }}>        {/* Your Stack screens go here */}</Stack></ThemeProvider>  );}

Viewing all articles
Browse latest Browse all 17158

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>