When implementing Using the gplus api in Apps Script I noticed that there didn’t seem to be an easy way to just get the the number of plus ones given a URL – but yet I knew it must be possible because the g+ button includes the option to show a count. I’m currently working on Displaying analytics data on site pages and wanted to combine Google Analytics with Google Plus counts for that.
[ note: this does not work anymore as Google removed gadgets on sites]
Scraping the source
When you dig into the page source with a g+ button with a count enabled, you find this:
<div id="aggregateCount" class="Oy">41</div>
So all you have to do is find out how this is triggered. While researching I came across this blog post by Helmut Granda, and what you need is this
https://plusone.google.com/u/0/_/+1/fastbutton?url=https://ramblings.mcpher.com&count=true
So now all that’s necessary is to scrape the web source to pull out the aggregateCount div. There’s not even any need for oAuth, as would probably be required if I was using the G+ api. I originally planned to use XMLService, but it’s a very trivial regex problem (and anyway it’s a hack) so I decided on using that instead. Here’s the code (I’m using Backing off on rate limiting since i’m going to be using this snippet in bulk and want to avoid rate limit problems)
/** * @param {string} url the url to get the plus 1 count for * @return {number} the plus one count */ // thanks to http://www.helmutgranda.com/2011/11/01/get-a-url-google-count-via-php/ for his PHP hack for the idea. function getPlusOneCount(url) { // this is hack from how the plus 1 button with count on a page gets its data. // the g+ api doesnt seem to have this capability, so here's a workaround url = "https://sites.google.com/a/mcpher.com/share/"; var query = "https://plusone.google.com/u/0/_/+1/fastbutton?count=true&url=" + encodeURIComponent(url); // do ab exp backoff in case this is called loads of times var result = cUseful.rateLimitExpBackoff(function () { return UrlFetchApp.fetch ( query); }); // find the result and return - XML service is unable to parse, so I'll just use a regex var match = /.*<div.*id=["']aggregateCount["'].*>\s*(\d+)\s*<.*/i.exec(result.getContentText()); if (match.length < 2) { Logger.log ("no g+ found for " + url); } return match.length === 2 ? Number (match[1]) : 0 ; }
ms | gplus hack | sharedCount |
average | 442.13 | 508.49 |
max | 653 | 6271 |
min | 322 | 22 |
function getSharedCount(url,key) { var query = "http://free.sharedcount.com/?apikey="+key+"&url=" + encodeURIComponent(url); // do ab exp backoff in case this is called loads of times var result = cUseful.rateLimitExpBackoff(function () { return UrlFetchApp.fetch ( query); },undefined,undefined,undefined,true); // find the result and return - XML service is unable to parse, so I'll just use a regex var r = result.getContentText(); return JSON.parse(r); }
Exceeded time limits
ms | gplus hack | sharedCount |
average | 41.95 | 44.78 |
max | 150 | 141 |
min | 9 | 10 |
// keep plus ones in cache for a few hours var cache = new cCacheHandler.CacheHandler(60*60*4,'sitePlusOnes');
function getSharedCount(url,key,optCache) { // we'll use cache if we can since these calls take up to a second to deal with var query = "http://free.sharedcount.com/?apikey="+key+"&url=" + encodeURIComponent(url); var cached; if (optCache) { cached = cache.getCache(query); } if (!cached) { // do ab exp backoff in case this is called loads of times var result = cUseful.rateLimitExpBackoff(function () { return UrlFetchApp.fetch ( query); },undefined,undefined,undefined,true); // find the result and return - XML service is unable to parse, so I'll just use a regex var r = result.getContentText(); if(optCache) { cache.putCache (r,query); } } else { var r = cached; } return JSON.parse(r); }
G+ hack
function getPlusOneCount(url,optCache) { // this is hack from how the plus 1 button with count on a page gets its data. // the g+ api doesnt seem to have this capability, so here's a workaround // we'll use cache if we can since these calls take up to a second to deal with var query = "https://plusone.google.com/u/0/_/+1/fastbutton?count=true&url=" + encodeURIComponent(url); var cached; if (optCache) { cached = cache.getCache(query); } if (!cached) { // do ab exp backoff in case this is called loads of times var result = cUseful.rateLimitExpBackoff(function () { return UrlFetchApp.fetch ( query); },undefined,undefined,undefined,true); // find the result and return - XML service is unable to parse, so I'll just use a regex var match = /.*<div.*id=["']aggregateCount["'].*>\s*(\d+)\s*<.*/i.exec(result.getContentText()); if (match.length < 2) { Logger.log ("no g+ found for " + url); } var r = match.length === 2 ? match[1] : '0' ; if(optCache) { cache.putCache (r,query); } } else { var r = cached; } return Number(r); }
For help and more information join our forum, follow the blog, follow me on twitter