Over two years ago I blogged about a demo I had built involving RSS and Google Analytics. The reason for that demo was simple. As an active blogger, I want to have an idea about how my recent content is doing. Google Analytics, however, doesn't have a way to recognize what my most recent content is. By combining a RSS feed and a Google Analytics API, I could create a mashup that reported exactly what I wanted - how my latest entries were doing.

In the time since I wrote that initial demo, a lot has changed. First off, the Google Feeds service I used was discontinued. Luckily there's multiple options around that (see my post, "Parsing RSS Feeds in JavaScript - Options").

The other change was to how I integrated with Google. There were multiple updates to the libraries I used - both in terms of authentication and working with Google Analytics. The Reporting API is now at version 4, and while still pretty complex, it's pretty powerful as well. Google has a really good JavaScript quick start that I used as a fresh start for the project. What I especially like is that they have very clear docs on the permissions you have to enable before using the code.

I'll be sharing my code, but note that I will not be sharing an online copy. My code will point the values you need to tweak in order to host this yourself. Before I share the code, a screen shot so you can see what I built:

Screen shot

As you can see, it's not much. Just a table with my latest entries as discovered via RSS and than a report on the page views for each. Ok, now the code. First, the HTML.

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>RSS Reporting</title>
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
	<meta name="google-signin-client_id" content="REPLACE ME">
	<meta name="google-signin-scope" content="https://www.googleapis.com/auth/analytics.readonly">
</head>
<body>

<div class="container">

	<h1>RSS Reporting</h1>

	<p class="g-signin2" data-onsuccess="loadRSS"></p>

    <table class='table table-striped table-bordered' id='reportTable'>
		<thead>
			<tr><th>URL</th><th>Page Views</th></tr>
		</thead>
	<tbody></tbody>
	</table>
</div>



<script src="app.js"></script>

<!-- Load the JavaScript API client and Sign-in library. -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script src="https://apis.google.com/js/client:platform.js"></script>

</body>
</html>

For the most part, this is ripped from the demo. Note the meta tags which allow the authentication to work. You don't see that in the screen shot above as I've got code to hide the login button after a successful login. What's cool is - the entirety of the authentication is basically that one button and the meta tags. Google handles the entire process. I love how easy that is. Note that the client id metatag would need to change for your own version of this. Now the JavaScript:

// Replace with your view ID.
const VIEW_ID = 'REPLACE ME';
const RSS = 'http://feeds.feedburner.com/raymondcamdensblog.xml';
const ROOT_URL = 'https://www.raymondcamden.com';

let $reportTable;

function loadRSS() {

	//hide the google auth button
	$('.g-signin2').hide();

    var yql = 'https://query.yahooapis.com/v1/public/yql?q=select%20title%2Clink%2Cdescription%20from%20rss%20where%20url%3D' +
	'%22'+encodeURIComponent(RSS)+'%22&format=json&diagnostics=true&callback=';

	$reportTable = $('#reportTable tbody');

    $.getJSON(yql, function(res) {
        rssItems = res.query.results.item;
		queryReports(rssItems);
    }, "jsonp");
}

// Query the API and print the results to the page.
function queryReports(items) {
	//first, ensure no more than ten
	items = items.slice(0,10);

	let reports = [];
	let reports2 = [];

	items.forEach((item) => {

		let newRow = `
<tr><td><a href="${item.link}" target="_new">${item.title}</a></td><td></td></tr>
		`;

		$reportTable.append(newRow);

		let link = item.link.replace(ROOT_URL,'');
		let report = {
			viewId:VIEW_ID,
			dateRanges:[
				{startDate:'2005-01-01', endDate:'today'}
			], 
			metrics:[
				{expression:'ga:pageviews'}
			],
			filtersExpression:'ga:pagePath=@'+link
		}
		if(reports.length < 5) {
			reports.push(report);
		} else {
			reports2.push(report);
		}
	});

	let p1 = gapi.client.request({
		path: '/v4/reports:batchGet',
		root: 'https://analyticsreporting.googleapis.com/',
		method: 'POST',
		body: {
			reportRequests: reports
		}
	});

	let p2 = gapi.client.request({
			path: '/v4/reports:batchGet',
			root: 'https://analyticsreporting.googleapis.com/',
			method: 'POST',
			body: {
				reportRequests: reports2
			}
		});

	Promise.all([p1,p2]).then((results) => {
		console.log('both done');		

		let reports = results[0].result.reports;
		//thank you SO: https://stackoverflow.com/a/9650855/52160
		reports.push.apply(reports, results[1].result.reports);

		for(var i=0;i<reports.length;i++) {
			let total = reports[i].data.totals[0].values[0];
    	    $("#reportTable tr:nth-child("+(i+1)+") td:nth-child(2)").text(total);
		}

	});
}

So in general, the proces is - get the RSS and then ask Google to analyze each URL. I used Yahoo's YQL feature to parse the RSS. Once I have the entries, I then switch to Google's Reporting API. This is where things get a bit weird.

The JavaScript library has one method and one method only - batchGet. This method lets you run up to 5 reports each. So while the library has one method, the reports are where you specify what you want to search for. Since a RSS feed has - normally - ten entries - my code is hard coded to work with 2 sets of 5 links. I could make this a bit more generic, but I don't want to. (I'm allowed to say that, right?) The batchGet method returns a promise, so I can chain them together with an "all" call to wait for both to be done and then just update my table.

And that's basically it. If this is helpful and you end up using the tool, please leave me a comment below.

Notes #

I could have used my JSONFeed source instead of my RSS. See my post from May about that. But I thought an RSS version may be more useful for other people since JSONFeed is still rather new.

Finally - damn - it's kind of depressing how low my page view counts are for my most recent content. My blog still gets very good traffic, a bit over 100K page views per month, but it's really kind of ego crushing to see how little traffic my latest content receives.