1
votes

I am trying to query the Google Analytics Reporting API from a node.js application.

I think I have set up everything correctly on the google-side of things including a service account, but I must be missing a piece.

My application successfully sends usage-data to Google, I can see it come in in the realtime view. I can also query the data using the interactive API explorer.

In my node.js code I authenticate with the API at server startup like so:

var googleapis_key = require('./config/google-api-key.json');
var googleapis = require('googleapis');
var googleapis_jwtClient = new googleapis.auth.JWT(
    googleapis_key.client_email, 
    null, 
    googleapis_key.private_key, 
    ["https://www.googleapis.com/auth/analytics.readonly"], 
    null);
var googleapis_analyticsreporting = googleapis.analyticsreporting('v4');

googleapis_jwtClient.authorize(function(err, tokens) {
    if (err) {
        lStartup.error(err);
        lStartup.error("Could not authenticate with google API. Analytics not available.");
    } else {
        lStartup.info("Successfully authenticated with google service-account.");
        lStartup.debug(googleapis_jwtClient.credentials);   
    }
});

(where lStartup is a log4js logger). I get a positive response back from Google, err is not set and the credentials logged to the console look convincing.

Then later when the relevant client request comes in my server tries to ask google for the data:

    var reportingrequests = {
        "reportRequests": [
            {
                "viewID": "138122972",
                "dateRanges": [{"startDate": "7daysAgo", "endDate": "yesterday"}],
                "metrics": [{"expression": "ga:users"}]
            }
        ]
    };

    logger.debug(JSON.stringify(reportingrequests));

    googleapis_analyticsreporting.reports.batchGet(
    {       
        "resource": reportingrequests,
        "auth": googleapis_jwtClient,
    },
    function(err, response) {
        if (err) {
            // Failure. Log and report to the client.
            console.error("Could not query the Google Analytics reporting API");
            console.error(err);

            res.writeHead(500, "Internal server error. (Google analytics:" + err + ")");
            res.end(JSON.stringify(err));
        } else {
            // Success, just serve googles result to the client.
            res.end(JSON.stringify(response));
        }
    }
);

The response is an error

[ { message: 'Invalid JSON payload received. Unknown name "view_id" at \'report_requests[0]\': Cannot find field.',
   domain: 'global',
   reason: 'badRequest' } ] }

What is it trying to tell me here? I do not have properties named view_id or report_requests in my JSON. Although they look suspiciously like mine de-camelcased.

1
I think the snake_case v. camelCase in the property names is a red herring. That is just the way the API handles things internally. I have removed the viewID property, the error message changes to "Parameter viewID must be set", note CamelCase left intact. I have changed the value to something known-bad. Same "unknown name "view_id"" message. So is my viewID wrong? I have checked it a number of times. - Marian Aldenhövel

1 Answers

5
votes

I hate self-answering, but I love solutions!

"viewID": "138122972",

should be

"viewId": "138122972",

Note the lowercase "d".

Ironically the clue to this is in the camelCase to snake_case-conversion. If the parameter name was "viewID" it would propably have been snake_cased to "view_i_d", which is not what is in the error message.

I feel stupid, but also happy to be able to go on.