Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't Post Events to Google Analytics from Google App Engine

I am trying to post an event to google analytics using Measurement Protocol from my Google App Engine (Java) web app.

I have tested the URL by submitting the URL directly, and it immediately shows up (realtime) in Google Analytics. But when I try to post it in the app nothing shows up.

So I assumed to start with my Java code was flawed (perhaps was), so I replaced my code with Google's example code to integrate from Google App Engine to Google Analytics here. I changed it a bit, but here are the key bits...

private static final URL GA_URL_ENDPOINT = getGoogleAnalyticsEndpoint();

private static URL getGoogleAnalyticsEndpoint() {
    try {
        return new URL("http", "www.google-analytics.com", "/collect");
    } catch (MalformedURLException e) {
        throw new RuntimeException(e);
    }
}

public boolean trackEvent(
        String category, String action, String label, String value) {

    try {

    Map<String, String> map = new LinkedHashMap<>();
    map.put("v", "1");             // Version.
    map.put("tid", gaTrackingId);
    map.put("cid", "555");
    map.put("t", "event");         // Event hit type.
    map.put("ec", encode(category, true));
    map.put("ea", encode(action, true));
    map.put("el", encode(label, false));
    map.put("ev", encode(value, false));

    HTTPRequest request = new HTTPRequest(GA_URL_ENDPOINT, HTTPMethod.POST);
    request.addHeader(CONTENT_TYPE_HEADER);
    request.setPayload(getPostData(map));

    HTTPResponse httpResponse = urlFetchService.fetch(request);

    // Return True if the call was successful.
    log.info("Response code for GA event is: " + httpResponse.getResponseCode());
    return httpResponse.getResponseCode() >= 200;

    } catch ( Exception e ) {
        //HANDLE EXCEPTION
        return false;
    }
}

private static byte[] getPostData(Map<String, String> map) {
    StringBuilder sb = new StringBuilder();
    for (Map.Entry<String, String> entry : map.entrySet()) {
        sb.append(entry.getKey());
        sb.append('=');
        sb.append(entry.getValue());
        sb.append('&');
    }
    if (sb.length() > 0) {
        sb.setLength(sb.length() - 1); // Remove the trailing &.
    }
    log.info("GA event string is: " + sb.toString());
    return sb.toString().getBytes(StandardCharsets.UTF_8);
}

private static String encode(String value, boolean required)
        throws UnsupportedEncodingException {
    if (value == null) {
        if (required) {
            throw new IllegalArgumentException("Required parameter not set.");
        }
        return "";
    }
    return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
}

When this bit of code is called, I get the parameter string out of my log file:

v=1&tid=UA-XXXXXXXX-1&cid=555&t=event&ec=settings&ea=autopost-on&el=rkAutoPost&ev=5

I also see that I get a 2xx response code from the call to google. But nothing shows up in GA interface (realtime or otherwise).

So then I try just doing a GET from inside my browser...

http://www.google-analytics.com/collect?v=1&tid=UA-XXXXXXXX-1&cid=555&t=event&ec=settings&ea=autopost-on&el=rkAutoPost&ev=5

... and that immediately hits GA realtime. So this tells me it isn't a problem with the content of the message.

Note I also created a brand new clean view to make sure nothing was being filtered out... did't help.

Any ideas please? Thank you!

like image 428
nickpharris Avatar asked Mar 27 '15 05:03

nickpharris


1 Answers

TL:DR; GA filters events from GAE via the User Agent request header. Override the User Agent via the measurement protocol's ua parameter.


Google Analytics (GA) is filtering Google App Engine (GAE) traffic based on the User Agent header containing the string "AppEngine-Google; (+http://code.google.com/appengine; appid: APPID)". I attempted to set the User Agent to a custom string, though as stated here, GAE appends the aforementioned string to any custom User Agent string and that is enough for GA to filter the events.

It is suggested in other answers that updating the view settings by unchecking the "Exclude all hits from known bots and spiders" Bot Filtering option would permit events from GAE though this did not work for me. Filtering bot traffic seems useful anyways so I wasn't too eager to uncheck this option anyways.

The solution was to override the User Agent via the measurement protocol's ua option which is not updated by GAE. The resulting parameter string from the example provided in the question would then be :

v=1&t=event&tid=UA-XXXXXXXX-1&cid=555&ec=settings&ea=autopost-on&el=rkAutoPost&ev=5&ua=Custom%20User%20Agent

Where my ua parameter is set to Custom User Agent.

Hope this saves someone some time in the future :)

like image 182
Dawson Avatar answered Sep 30 '22 04:09

Dawson