James Hood
James Hood

Reputation: 21

Get data from google analytics api in chrome extension?

I am trying to develop a form abandonment heat mapper

function newMarkup(id, uniqueHits){
var min = Math.min.apply(null,uniqueHits);
var max = Math.max.apply(null,uniqueHits);
var med = max / 2;
for(var num = 0; num < id.length; num++){
    styleElement(id[num], uniqueHits[num], min, max, med);
}}

function styleElement(element, value, min, max, med){
    var el = $("[id$=" + element + "]");
    if(el.prop('nodeName') === "INPUT"){
        if(value == max){
            el.addClass('very-good');
        }
        if(value < max && value > med){
            el.addClass('good');
        }
        if(value == med){
            el.addClass('average');
        }
        if(value < med && value > min){
            el.addClass('not-so-good');
        }
        if(value == min){
            el.addClass('poor');
        }
    } else {
        el = el.next();
        if(value == max){
            el.addClass('very-good');
        }
        if(value < max && value > med){
            el.addClass('good');
        }
        if(value == med){
            el.addClass('average');
        }
        if(value < med && value > min){
            el.addClass('not-so-good');
        }
        if(value == min){
            el.addClass('poor');
        }
    }
}

and I am wondering if it is possible to do the call to the api from a chrome extension?

Essentially I am trying to do this call to get the data:

gapi.client.analytics.data.ga.get({
    'ids': 'ga:' + profileId,
    'start-date': '7daysAgo',
    'end-date': 'today',
    'metrics': 'ga:uniqueEvents',
    'dimensions': 'ga:eventLabel',
    'sort':'-ga:uniqueEvents',
    'filters': "ga:eventCategory==Form Field Tracking - /join"
})

I tried do create my heatmapper by having an iFrame in an MVC web application but because of the trouble of trying to send data across domains, I gave up on that.

I would like to know if it's possible to get data from the analytic's API from a chrome extension? I'd imagine it would have to be done in a similar fashion as how google scripts uses the analytics API (using a service account) but I have been unable to find any documentation or find out if this is even possible. (Example of code in scripts)

function runReport(profileId) {
    var today = new Date();
    var oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);

    var startDate = Utilities.formatDate(oneWeekAgo, Session.getTimeZone(), 'yyyy-MM-dd');
    var endDate = Utilities.formatDate(today, Session.getTimeZone(), 'yyyy-MM-dd');
    var tableId  = 'ga:' + profileId;
    var metric = 'ga:uniqueEvents';
    var options = {
        'dimensions': 'ga:eventLabel',
        'sort':'-ga:uniqueEvents',
        'filters': "ga:eventCategory==Form Field Tracking - /join"
    };
    var report = Analytics.Data.Ga.get(tableId, startDate, endDate, metric, options);
}

I'd really appreciate any help or advice anyone has for me. I am trying to query the google analytic's API from a chrome extension. Is this possible?

Upvotes: 2

Views: 429

Answers (1)

woxxom
woxxom

Reputation: 73686

Not tested on GA specifically but this is the general method of working with scripts that require external server for the API:

  1. The content script can't make requests to other sites so it should ask the background page to do it by sending a message
  2. The background page includes ga.js script referenced in the manifest, this file must be present in the extension, it's not a remotely loaded script.
  3. The background page can communicate with the external API server after we add the corresponding CSP rule (added in the manifest)
  4. Now the message from step 1 is received by the background page listener, which invokes GA and sends the results back to the content script of the original tab (tabId was saved when the first message was received).

  • manifest.json:

    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "run_at": "document_start",
            "all_frames": true,
            "js": ["content.js"]
        }
    ],
    "background": {
        "scripts": ["background.js", "ga.js"]
    },
    "content_security_policy": 
        "script-src 'self' https://ssl.google-analytics.com; object-src 'self'",
    .............
    
  • content.js:

    chrome.runtime.sendMessage({type: "getGA", data: some_data_for_GA});
    chrome.runtime.onMessage.addListener(function(msg) {
        if (msg.type == "GA") {
            // apply msg.data to the page elements
            ...................
        }
    });
    
  • background.js:

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        var tabId = sender.tab.id, frameId = sender.frameId;
        if (msg.type == "getGA") {
            gapi.client.analytics.data.ga.get({
                ..................... // use msg.data if needed
            }).execute(function(response) {
                sendMessageToFrameId(tabId, frameId, {type: "GA", data: response});
            });
        }
    });
    
    function sendMessageToFrameId(tabId, frameId, msg) {
        // 1. frameId works since Chrome 41 and throws on prior versions
        // 2. without frameId Chrome 45 sends the message to wrong tabs
        try { chrome.tabs.sendMessage(tabId, msg, {frameId: frameId}); }
        catch(e) { chrome.tabs.sendMessage(tabId, msg); }
    }
    

Upvotes: 0

Related Questions