Search code examples
google-app-enginegoogle-analyticsmeasurement-protocol

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!


Solution

  • As with all the other questions I have read on similar subject, it was a stupid mistake: problem was that I did indeed create a new, clean view in GA, but when I created it I checked...

    Exclude all hits from known bots and spiders

    ... so all events being generated by calls on Google App Engine were being filtered out. Ugh.