This one is about what developers hate most: finding out why stuff doesn’t work and fixing it.
There are quite a lot of moving pieces here, so debugging includes a couple of different aspects and we need to use different tools. I will also try to explain some of the things I have just sort of thrown at you in the last posts, because understanding something makes it easier to work with it.
The first thing you want to do before you start debugging is to enable debug logging:
You can do that right after initialisation of the object in your main Activity’s
onCreate() method, like so:
What does that do? Well, it’ll give you a lot of output in LogCat:
Notice how you can actually see the tracking request in there? The full URL is right there! Awesome.
This is comparable to debugging a web site using Charles, insofar as you can see all the parameters and therefore quickly check whether your implementation makes any sense.
My guess is that you can get very far just using LogCat. The remainder of this article is for trickier cases and of course for your amusement.
So, where else do we look and what else do we look for?
You might remember the article about the stages of processing that every hit you send goes through. Those stages are identical for mobile apps except for the first part, which I called “On the Page”.
There are arguably no pages in your app, only Views (iOS) and Activities (Android). Still, the general idea is the same:
- You assign values to “Variables”, or rather into a
HashMapof Context Data, because the Mobile SDKs v4.x+ do not support old-style variables anymore.
- You could use a Data Layer if you want. I feel that there’s less need to do so for mobile apps, mostly because the View/Activity idea means you are always working on a relatively small and restricted entity, not an enormous page that can potentially scroll forever and contain loads of elements.
- You will add tracking to Actions (Buttons or links) so you can track what people do in your app.
At the time of this writing, you’re unlikely to use tag management in an app. I hope that will change at some point!
The first level of debugging is in your Java code.
You would place a break point on any
trackXYZ() methods and just check what your
HashMap contains at that point.
Remember with the v4.x+ SDKs you are using Context Data, so everything that you want to track has to be in that
The second level is the debug logging that goes into LogCat as described above.
You can see all the parameters that will be sent and then the call that has been sent.
This gives you two things above and beyond level 1:
- you can see whether the tracking call has actually happened (or the system thinks it has, who knows what happens outside our control!), and
- you see all the other data that the SDK puts onto the call, beyond just your Context Data.
The third level is “on the wire” (or “on air”), using a tool like Charles or Bloodhound, Adobe’s very own debugger made for mobile.
You won’t get more data here than on level 2, but you will get a better feeling for whether the tracking has actually been sent out.
Also, there is a proper interface that helps debugging. Beats LogCat and maybe even Charles.
(Did you notice something in the screenshot? If so then you’re a better troubleshooter than I am… there are lifecycle calls there (2) and calls as a result of buttons being pressed (another 2), but there are no tracking calls on the Activity, simply because I originally forgot the
trackState() calls. D’oh!)
How does that work?
Tracking calls are HTTP GET requests with some payload in the URL parameters. A debugger must capture or proxy that request. It will then give you more or less beautified access to the data.
You know where I’m going with this, don’t you?
You need to tell your device, emulator or simulator to use a proxy server for all HTTP requests, and that proxy server has to be your debugger (Charles, Bloodhound, …).
Pro Tip: make sure your debugger is listening on the right network adapter! Most machines have at least two (wired and wireless) and VPNs, VMs and other software can add to that.
When I first ran Bloodhound, I was naively presuming it would listen on
localhost, but it doesn’t. You have to press the “Stop” button, change the network, then hit “Start”.
Don’t know where to change the proxy on your device or emulator?
Look for the “[ ] Show Advanced Options” checkbox under “Modify Network”. If you tick that box, new settings will appear, notably for proxy and port.
If you’re using an emulator, you need to change the APN settings of your (fake) mobile network. The emulator emulates a 3G connection, not WiFi.
So what’s the next “level”?
You have two options:
- look at the reports in
SiteCatalystReports & Analytics, or
- get more or less raw data out of the system.
I presume you like the raw data better, so let me tell you what I am talking about. Before I do that, let me also say that it is actually unlikely that you will debug at this level. Unlikely but not impossible. The big use case is when you can see data going in but it won’t show up in any report. While this is most often a case of missing Processing Rules, sometimes it must be debugged.
Now, depending on whether your friendly marketer has signed up for “Analytics” or “Analytics Premium”, you have one or two ways of getting raw data out. Let me start with the one that you might not have.
Analytics Live Stream
I don’t want to go too deep into the Analytics Live Stream because a) not many people are using it so far and b) the data is very similar to that in a usual Data Feed, except that it is transported differently.
Rather than receiving files via FTP, the Analytics Live Stream is actually a stream. You use Apache-httpclient, java.net.URLConnection, Python and ruby HTTP clients, or libcurl to receive data from the system. That data is usually at most a couple of seconds old (what we’d call “real time” in the analytics world).
The Developer Connection has some good documentation on Analytics Live Streams including sample code.
Clickstream Data Feed
“Data Feeds” allow you to get raw data delivered in CSV (or rather TSV, tab-separated) files to an FTP server of your choice.
Each line in the file represents on hit that your app (or web site) has sent in. And each column represents some data, a “variable”, meta data (like the visitor IDs), or technical data about the hit itself (such as the time it was received, the rsid or the version of your
How would you use a Data Feed file to debug?
Depending on what exactly you want to know, you will likely check the values in a particular column. The trick is to be able to filter the rows, or you’ll drown in data. Tools like
cut, or even
sed are very helpful at this level. But let’s put that aside for now and reserve a posting for it. Some people load the files into Access and look at them in there.
How do you get a Data Feed?
Your friendly marketer can speak to Adobe (the AM or CSM or even ClientCare) to get it done.
Once they have set it up, it’ll deliver a file a day (or sometimes a file every hour).
You can use an Adobe FTP server, but make sure you pull the file before the next one arrives. Those FTP servers have limited space. Might be better if you can provide an FTP server that you can control…
And last but not least, you can analyse the data in the reports, ideally together with your friendly marketer. She will be able to tell you where to look and she’ll help you interpret what you see in the reports.
Sometimes this is straight-forward. The buttons I made for my completely useless app are a good example. Whenever a button is pressed or tapped, I am sending the button ID and some other data, which in the backend is transformed into an eVar and an event.
Because they always happen at the same time, I can easily test this: launch the app for the first time on a given day, press one of the buttons twice and another one once. Wait for Reports & Analytics to process the data (see latency in SC15 for details), then pull up the report for the eVar and select the event as the metric.
You should see the button IDs, each in a line. You should also see a “2” on one line, a “1” on the other, and a sum of “3”.
Check that the button IDs correspond to the buttons you pressed and bingo, you’re fine. If you do not see a “2” and a “1” or the button IDs are wrong, go back to your code, run a level 1
One cool feature of the v4.x SDKs is that your marketer can see how exactly she managed to get people to download and launch your app.
I’m saying “feature of v4.x” and you will immediately point out that I have written about this back in November 2013, back when the SDK was at v3.x, right? Yes, indeed.
There was a small window, when this actually worked for Google Play and Android with a v3.x library. It was in this window that I wrote the article. Unfortunately, the window closed when Google released v4.3(?) of the Google Play Services and changed the way app installs work on Android.
But now we’re back in business!
The old article from November 2013 mostly still stands. The only difference is in the timing.
Where formerly, the
BroadcastReceiver was called before app launch, it will nowadays be called later, hence the
referrerTimeout setting in
ADBMobileConfig.json. The setting tells the library to wait with the initial lifecycle tracking call for a bit, so that the Google Play Services have time to send an Intent and the
BroadcastReceiver can receive and grab it.