in Tricks

issues with Google Analytics and iOS 7 background fetch

Since the introduction of iOS 7, there’s an abundance of articles that explain how to use iOS 7′s background fetch to download data for your apps while the phone is in it’s downtime.

Background fetch can be used to update weather information, traffic report status, load new articles, etc. It’s a way for your app to reach your server and update the user’s screen during downtimes (phone not being used, phone is sleeping and being charged).

iOS uses a bunch of factors before giving your app the precious time-slice (around 30sec max) in order for your app to do its business. The faster you execute the process, the more chances the OS will give you future time-slices. The more processor intensive you are, the less likely for the OS to give you time in the future.

This is all well and good, and I have recently launched an app update that uses this feature to the App Store.

What came next was perplexing…

I have noticed that my Google Analytics sessions wildly increased, almost by a factor of 4 folds (went from 15K to 60K daily sessions). I have also noticed that my App’s start page (let’s call it Home page) is accounting for most of the views. At first I was thinking that there might be an issue with Google Analytic’s newest library as I have updated it in my project (went from v3.0.3 to v3.0.8). But digging further, I noticed that my background-fetch url was being solicited by the same number of my session increase (45K daily) which Google Analytics isn’t tracking. But how come Google Analytics is showing me Home page hits increase?

I came across this passage in Apple reference documentation (emphasis mine)

In iOS 7 and later, an app that retrieves content regularly from the network can ask the system for background execution time to check for new content. You enable support for background fetches from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the UIBackgroundModes key with the fetch value in your app’s Info.plist file.) At appropriate times, the system gives background execution time to the apps that support this background mode, launching the app directly into the background if needed. The app object calls the application:performFetchWithCompletionHandler: method of its app delegate to let you know when execution time is available.

Reference: Apple documentation

This got me realizing that didFinishLaunchingWithOptions: can or will be called at each background-fetch calls, something all the tutorials don’t point out for obvious reasons, but can catch even the best of us off-guard.

Now according to Google Analytics documentation it mentions that the best place to put Google Analytics initialization code is in didFinishLaunchingWithOptions:with something like this:

[[GAI sharedInstance] trackerWithTrackingId:@"UA-XXXXXXXX-X"];

Since I was using the default code from Google Analytics’ website, my didFinishLaunchingWithOptions: looked something like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
   [[GAI sharedInstance] trackerWithTrackingId:@"UA-XXXXXXXX-X"];
   // init UI [...]
   return YES;

What ended happening, even though the app was launching in background, didFinishLaunchingWithOptions: was being called before performFetchWithCompletionHandler:, thus the UI was being initialized and UIViews were being loaded creating a false screen view event that gets sent to Google Analytics.

In other words, Google Analytics was reporting exactly what was going on with my app: Screens were being loaded during my background-fetch cycles.

To fix this issue in my app, I took care to differentiate between foreground and background startup states in didFinishLaunchingWithOptions: and load the UI only if we’re not being started in background state.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    [[GAI sharedInstance] trackerWithTrackingId:@"UA-XXXXXXXX-X"];
    if ([application applicationState] == UIApplicationStateBackground) {
    // background state
    // handle pushnotifications/localnotifications/background-fetch
    } else {
    // foreground state
    // init UI [...]

This way, it resolves the Google Analytics spike in screens and sessions that were not representing reality.

What do you guys think? do you have similar stories? please share.

  • zonabi

    good call. been wonderin the same. does it affect session times too? what other ways does it adversely affect tour metrics.

    is this still a problem in latest sdk and ga process?


    • mike

      yes. The thing is, GA lib get loading in didFinishLaunchingWithOptions, its a programming logic that must be taken care of. The take away is that application:didFinishLaunchingWithOptions get called even for background fetch

  • Guest

    yes. The thing is, GA lib get loading in didFinishLaunchingWithOptions, its a programming logic that must be taken care of. The take away is that application:didFinishLaunchingWithOptions get called even for background fetch :)

  • Brian Plattenburg

    So I’m seeing something really similar going on with my app, but I’m not using background fetch. Is it possible that something else, like background location updates could be causing the same behavior?

    • mike

      It could be.. Make sure when you launch GA that the state of the app is what you’re expecting it to be: active