Categories
tech

Integrating Google Analytics with Eleventy

Before I start, this text is no longer about including Google Analytics in your website. Google supplies a HTML/JS snippet you’ll simply reproduction and paste into your code and that’s the reason about so simple as you’ll get. For Eleventy, you might do that to your primary structure record so it is come with far and wide. There ya cross, if that is what you sought after, you’ll forestall studying. 😉 This article is set tips on how to combine Google Analytics knowledge into your website, and is a followup to the weblog put up I did previous this week demonstrating how to try this with Netlify Analytics.

Hopefully you have got learn that earlier article as this one will practice a an identical development. As with maximum issues Google API similar, I spent an enormous period of time with authentication and authorization problems and far much less time the use of their API. It’s gotten some extent the place I dread operating with their APIs. Not as a result of their APIs do not paintings smartly, however as a result of authentication appears to be so tough, particularly if you are no longer the use of OAuth. Alright, sufficient of a rant, let’s do that.

Getting the Analytics

Google Analytics has a REST API that permits you to get any reporting data out by means of API calls that you’d have to be had by means of the dashboard. Using it in a Node.js setting calls for you to first create a carrier account. Generate the JSON key for that account and put it aside in your record gadget. (I’ll use the record gadget for this data within the first portion of the thing, after which discuss tips on how to transfer clear of that.)

Next, you will want to set up the googleapis bundle. This incorporates wrappers for all in their supported APIs.

Now for the an important section. When you create a carrier account, it is going to come with an e mail cope with within the knowledge. It will glance one thing like this:

"client_email": "[email protected]",

Yes, “damnga” is “rattling google analytics” – I used to be pissed off. Copy the e-mail cope with, cross in your Google Analytics dashboard, and upload it as a consumer to the valuables your operating with. This will also be accomplished by means of the Admin hyperlink.

View User Management

All it wishes is “Read & Analyze” permissions. While to your dashboard, additionally click on the “View Settings” hyperlink and get your View ID:

View ID

Alright, as soon as you have got accomplished that, let’s take a look at the code, little by little in the beginning. Start off initializing the library:

const {google} = require('googleapis');
let creds = require('./credentials4.json'); const auth = new google.auth.GoogleAuth({ credentials:creds, scopes: ['https://www.googleapis.com/auth/analytics.readonly']
}); const ap = google.analyticsreporting({ model:'v4', auth:auth
});

Now you are ready to make reviews. The API helps batching so you’ll ask for more than one issues immediately. In common maximum Google APIs are easy as soon as you have got gotten previous the auth section, however the Analytics API is fairly complicated. I sought after a record over the last seven days of web page perspectives. Here’s how I did it:

const res = anticipate ap.reviews.batchGet({
requestBody: { reportRequests: [ { viewId: '73496341', dateRanges: [ { startDate: '7daysAgo', endDate: 'yesterday', }, ], dimensions:[ { "name": 'ga:pagePath' }, ], metrics: [ { expression: 'ga:pageviews', }, ], orderBys:[ { fieldName: "ga:pageviews", sortOrder:'DESCENDING' } ], pageSize:10 }, ],
},
});

From what I will acquire, metrics is what you’re inquiring for and dimensions is what you need again, on this case a record of the trail that generated the web page perspectives. I do sorting and proscribing as smartly. The outcome knowledge is complicated as smartly. I’ll proportion it right here however be at liberty to skim it:

{ "rows": [ { "dimensions": [ "/article/perform-date-manipulations-based-on-adding-or-subtracting-time/" ], "metrics": [ { "values": [ "153" ] } ] }, { "dimensions": [ "/" ], "metrics": [ { "values": [ "41" ] } ] }, { "dimensions": [ "/article/create-a-random-nonce-string-using-javascript/" ], "metrics": [ { "values": [ "16" ] } ] }, { "dimensions": [ "/all/" ], "metrics": [ { "values": [ "8" ] } ] }, { "dimensions": [ "/article/traversing-dom-subtrees-with-recursive-walk-the-dom-function/" ], "metrics": [ { "values": [ "7" ] } ] }, { "dimensions": [ "/article/check-if-a-value-is-an-array/" ], "metrics": [ { "values": [ "5" ] } ] }, { "dimensions": [ "/tag/array/" ], "metrics": [ { "values": [ "5" ] } ] }, { "dimensions": [ "/article/map-a-nodelist-to-an-array-of-properties/" ], "metrics": [ { "values": [ "3" ] } ] }, { "dimensions": [ "/submit/" ], "metrics": [ { "values": [ "3" ] } ] }, { "dimensions": [ "/tag/math/" ], "metrics": [ { "values": [ "3" ] } ] } ], "totals": [ { "values": [ "275" ] } ], "rowCount": 30, "minimums": [ { "values": [ "1" ] } ], "maximums": [ { "values": [ "153" ] } ]
}

I grew to become this into more practical knowledge like so:

let record = res.knowledge.reviews[0].knowledge;
let knowledge = record.rows.map(r => {
go back { trail: r.dimensions[0], perspectives: r.metrics[0].values[0]};
});

Which offers me the better:

[ { "path": "/article/perform-date-manipulations-based-on-adding-or-subtracting-time/", "views": "153" }, { "path": "/", "views": "41" }, { "path": "/article/create-a-random-nonce-string-using-javascript/", "views": "16" }, { "path": "/all/", "views": "8" }, { "path": "/article/traversing-dom-subtrees-with-recursive-walk-the-dom-function/", "views": "7" }, { "path": "/article/check-if-a-value-is-an-array/", "views": "5" }, { "path": "/tag/array/", "views": "5" }, { "path": "/article/map-a-nodelist-to-an-array-of-properties/", "views": "3" }, { "path": "/submit/", "views": "3" }, { "path": "/tag/math/", "views": "3" }
]

Woot. That labored, now let’s get this into Eleventy!

Integrating with Eleventy

As with my earlier demo, I moved my Node code into an Eleventy _data record referred to as popularpages.js. Here it’s:

require('dotenv').config(); const {google} = require('googleapis');
let creds = JSON.parse(procedure.env.GOOGLE_AUTH); const auth = new google.auth.GoogleAuth({ credentials:creds, scopes: ['https://www.googleapis.com/auth/analytics.readonly']
}); const ap = google.analyticsreporting({ model:'v4', auth:auth
}); module.exports = serve as() { go back new Promise(async (unravel, reject) => { const res = anticipate ap.reviews.batchGet({ requestBody: { reportRequests: [ { viewId: '73496341', dateRanges: [ { startDate: '7daysAgo', endDate: 'yesterday', }, ], dimensions:[ { "name": 'ga:pagePath' }, ], metrics: [ { expression: 'ga:pageviews', }, ], orderBys:[ { fieldName: "ga:pageviews", sortOrder:'DESCENDING' } ], pageSize:10 }, ], }, }); let record = res.knowledge.reviews[0].knowledge; let knowledge = record.rows.map(r => { go back { trail: r.dimensions[0], perspectives: r.metrics[0].values[0]}; }).clear out(d => { if(d.trail.indexOf('article') === -1) go back false; go back true; });; unravel(knowledge); }); };

Outside of “shaping” it into the layout Eleventy needs, there may be two primary adjustments. First, I load in my Google auth by means of an atmosphere variable. I took the JSON, got rid of the road breaks, and set it as an atmosphere variable in the community and as an atmosphere variable in my Netlify website settings.

The 2d alternate is the clear out name. For the website in query (JavaScript Cookbook), I simplest sought after to turn widespread articles and no longer come with tag pages or different pages. As with the ultimate instance, that is the section you might wish to tweak to your personal wishes.

Then I put it on my house web page.

<h3>Popular Articles</h3> {% for article in popularpages restrict:5 %}  toData: collections.articles % <a href="{{article.trail}}">{{articleData.name}}</a> - {% dateFormat articleData.printed %}<br/>
{% endfor %}

The toData clear out there may be how I “translate” a trail into the right kind Eleventy knowledge together with the name and e-newsletter date. While the clear out is just about the similar as my earlier instance, right here it’s:

let titleArticleCache = {};
eleventyConfig.addFilter('toData', (p, articles) => { if(titleArticleCache[p]) go back titleArticleCache[p]; for(let i=0;i<articles.duration;i++) { if(articles[i].url == p) { titleArticleCache[p] = { name: articles[i].knowledge.name, printed: articles[i].knowledge.printed}; go back titleArticleCache[p]; } } // cache that we could not fit titleArticleCache[p] = { name: ''}; go back titleArticleCache[p];
});

And this is the way it appears:

Example output

You can see it reside on the JavaScript Cookbook and your complete code on the GitHub repo: https://github.com/iandroid.eu/javascriptcookbookstatic