DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Let’s Build an End-to-End NFT Project Using Truffle Suite
  • The Ultimate Guide to React Dashboards Part 1: Overview and Analytics
  • Working With Account APIs for Google Tag Manager and Google Analytics
  • Understanding Google Analytics 4, Server-Side Tracking, and GDPR Compliance

Trending

  • LLMs for Bad Content Detection: Pros and Cons
  • Database Monitoring: Key Metrics and Considerations
  • Auto-Scaling DynamoDB Streams Applications on Kubernetes
  • Demystifying Enterprise Integration Patterns: Bridging the Gap Between Systems
  1. DZone
  2. Data Engineering
  3. Data
  4. Using the Google Analytics Embed API to Build a Dashboard

Using the Google Analytics Embed API to Build a Dashboard

Raymond Camden user avatar by
Raymond Camden
·
Jul. 08, 15 · Tutorial
Like (0)
Save
Tweet
Share
8.29K Views

Join the DZone community and get the full member experience.

Join For Free

about a year and a half ago i created a demo ( proof of concept – dashboard for google analytics ) of a google analytics dashboard. this demo was entirely client-side based and made use of the api libraries google created. for the most part, the process was fairly simple. after i figured out how to authenticate the user and query the data, i spent more time making it look pretty than actually working with the api, which is a good thing. more recently i discovered the new analytics embed api . the cool thing about the embed api is that it greatly simplifies the authentication/authorization aspect of getting analytics data and even provides built in charting capabilities. i blogged an example ( quick example of the google analytics embed api ) and i thought it might be fun to revisit my dashboard concept using this simpler api.

before i show the code behind this demo, let me share a screen shot so you can see it in action. i switched to a new charting library for this demo ( chartjs ) mainly because google used it themselves in one of their demos. i didn’t spend much time making this pretty – i was going for ‘quick impact’ in terms of visuals. obviously though it could be better.

shot1

each chart represents one of my properties. each line represents page views per days, with the darker blue being the most recent page seven days and the lighter gray being the seven days before that.

the code is made up of several parts. the authentication, as i said, is handled almost entirely by the embed api.

gapi.analytics.ready(function() {

  var client_id = '818125206534-g1r0datdtu9serq2pf9cp5vkuih3h8pv.apps.googleusercontent.com';

  gapi.analytics.auth.authorize({
    container: 'auth-button',
    clientid: client_id,
    userinfolabel:""
  });

  gapi.analytics.auth.on('success', function(response) {
    //hide the auth-button
    document.queryselector("#auth-button").style.display='none';
    console.log("get profiles");
    getprofiles(function(profs) {
      window.profiles = profs;
      processprofiles();      
    });

  });

  chart.defaults.global.animationsteps = 60;
  chart.defaults.global.animationeasing = 'easeinoutquart';
  chart.defaults.global.responsive = true;
  chart.defaults.global.maintainaspectratio = false;

});

in order to get profiles for my account, i make use of a management api. getprofiles handles fetching, and caching, this result. (i use caching as i had planned, still plan on, adding a few additional filtering options to the report.)

function getprofiles(cb) {
  //do we have a cached version?
  if(sessionstorage["gaprofiles"]) {
    console.log("profiles fetched from cache");
    cb(json.parse(sessionstorage["gaprofiles"]));
    return;
  }

  gapi.client.analytics.management.accounts.list().then(function(res) { 
    var accountid = res.result.items[0].id;
    var profiles = [];
    gapi.client.analytics.management.webproperties.list({'accountid': accountid}).then(function(res) {

    res.result.items.foreach(function(item) {
    if(item.defaultprofileid) profiles.push({id:"ga:"+item.defaultprofileid,name:item.name});
    });
      sessionstorage["gaprofiles"] = json.stringify(profiles);    
      cb(profiles);      
    });
  });
}

note that i do not make use of promises in this block and that’s a mistake. i make use of it a bit later in another function so i need (well, i want) to be consistent. now for the fun part. for all of my properties, i need to fetch data for each site. i was able to rip code from one of google’s demos but i quickly ran into rate limit issues. to get around this, i single thread the calls and add a slight delay.

//credit: https://ga-dev-tools.appspot.com/embed-api/third-party-visualizations/
function query(params) {
  return new promise(function(resolve, reject) {
    var data = new gapi.analytics.report.data({query: params});
    data.once('success', function(response) { resolve(response); })
        .once('error', function(response) { reject(response); })
        .execute();
  });
}

function makecanvas(id) {
  var container = document.getelementbyid(id);
  var canvas = document.createelement('canvas');
  var ctx = canvas.getcontext('2d');

  container.innerhtml = '';
  canvas.width = container.offsetwidth;
  canvas.height = container.offsetheight;
  container.appendchild(canvas);

  return ctx;
}

function processprofiles() {
  console.log("working on profile "+profiles[curprofile].name);

  var now = moment();
  var id = profiles[curprofile].id;

  var thisweek = query({
    'ids': id,
    'dimensions': 'ga:date,ga:nthday',
    'metrics': 'ga:pageviews',
    'start-date': moment(now).subtract(8, 'day').format('yyyy-mm-dd'),
    'end-date': moment(now).subtract(1,'day').format('yyyy-mm-dd')
  });

  var lastweek = query({
    'ids': id,
    'dimensions': 'ga:date,ga:nthday',
    'metrics': 'ga:pageviews',
    'start-date': moment(now).subtract(15, 'day').subtract(1, 'week')
    .format('yyyy-mm-dd'),
    'end-date': moment(now).subtract(8, 'day').subtract(1, 'week')
    .format('yyyy-mm-dd')
  });


  promise.all([thisweek, lastweek]).then(function(results) {
    console.log("promise.all");console.dir(results);

    var data1 = results[0].rows.map(function(row) { return +row[2]; });
    var data2 = results[1].rows.map(function(row) { return +row[2]; });
    var labels = results[1].rows.map(function(row) { return +row[0]; });

    var totalthisweek = results[0].totalsforallresults["ga:pageviews"];
    var totallastweek = results[1].totalsforallresults["ga:pageviews"];
    var percchange = (((totalthisweek - totallastweek) / totallastweek) * 100).tofixed(2);
    console.log(totallastweek, totalthisweek, percchange);

    labels = labels.map(function(label) {
      return moment(label, 'yyyymmdd').format('ddd');
    });

    var data = {
      labels : labels,
      datasets : [
        {
          label: 'last week',
          fillcolor : 'rgba(220,220,220,0.5)',
          strokecolor : 'rgba(220,220,220,1)',
          pointcolor : 'rgba(220,220,220,1)',
          pointstrokecolor : '#fff',
          data : data2
        },
        {
          label: 'this week',
          fillcolor : 'rgba(151,187,205,0.5)',
          strokecolor : 'rgba(151,187,205,1)',
          pointcolor : 'rgba(151,187,205,1)',
          pointstrokecolor : '#fff',
          data : data1
        }
      ]
    };

    var titlestr = profiles[curprofile].name + " ";
    if(totallastweek > 0 && totalthisweek > 0) {
      if(percchange < 0) {
        titlestr += "<span class='down'>(down "+math.abs(percchange) + "%)</span>";
      } else {
        titlestr += "<span class='up'>(up "+percchange + "%)</span>";      
      }
    }

  $("body").append("<div class='reportcontainer'><div class='charttitlecontainer'>"+titlestr+"</div><div class='chartcontainer' id='chart-"+curprofile+"-container'></div></div>");

    new chart(makecanvas('chart-'+curprofile+'-container')).line(data);

    if(curprofile+1 < profiles.length) {
      curprofile++;
      //settimeout to try to avoid ga rate limits
      settimeout(processprofiles,200);
    }
  });
}

and that’s basically it. as i said, i’d like to add a few options to this. specifically, the ability to compare the current and past 30 days as well as this year versus the past. i’d also like the ability to dismiss/hide some sites i don’t care about. i could use localstorage to remember those properties and hide them automatically.

want to see the complete code and test it yourself? check out the online demo here: http://static.raymondcamden.com/ga_embed/test10.html

Google (verb) Analytics API Dashboard (Mac OS) Build (game engine)

Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Let’s Build an End-to-End NFT Project Using Truffle Suite
  • The Ultimate Guide to React Dashboards Part 1: Overview and Analytics
  • Working With Account APIs for Google Tag Manager and Google Analytics
  • Understanding Google Analytics 4, Server-Side Tracking, and GDPR Compliance

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: