How to Set Up Google Analytics for Canvas

26 104 23.3K

Using Google Analytics means that your institution is subject to Google's terms of service. Please verify with your institution's legal team before installing Google Analytics in your Canvas instance to ensure that you are in compliance with relevant laws and regulations.

This outlines the use of Google Analytics without Google Tag Manager. This is an old implementation. You may want to look into some of these other community resources if you are configuring Google Analytics for the first time. It does require a little bit more upfront time to get configured, but is considered the new way of doing Google Analytics.

New Custom Dimensions & Updated Script - May 31, 2019

A core code change to Canvas on Aug 28, 2019 may have broken your implementation of Google Analytics. Please install the updated code to restore functionality.

The steps below will help you get set up to use Google Analytics for Canvas. If you'd like to know more about why you might want to do this, please watch this Canvas Live session.

Create a Google Analytics Account

  1. Sign into Google
  2. Navigate to  and click Sign Up
  3. Fill out the Form as desired, using your Canvas url in the website url field (eg: (or vanity url if you have one)
  4. Click "Get Tracking ID" button
  5. Accept Terms of Service
  6. Copy down the "Tracking ID" (eg: UA-12345678-1)

Set Up Tracking By User-ID New

Allows for more accurate session unification based on the user's Canvas ID, granting better user overtime metrics

  1. Navigate to the Admin Portal (If you just created your account you are already there)

  2. Click on "Tracking Info" to expand the menu item

  3. Click on "User-ID" option

  4. Read the agreements and follow the prompts

Add Custom Dimensions to Google Analytics Updated

This will let you pass custom variables from Canvas to Google Analytics such as User ID's, User Names, Course ID's and more.

  1. Navigate to the Admin Portal (If you just created your account you are already there)
  2. Click on "Custom Definitions" menu item
  3. Click on "Custom Dimensions menu item
  4. Click "+ NEW CUSTOM DIMENSION" button
  5. Add the following dimensions in order (If your index number is incorrect shared dashboards may not work)314355_pastedImage_7.png

Add Custom Javascript to Your Institution's Theme Editor

** Custom Javascript has been known to break things in Canvas. As of writing this post, May 31, 2019, it is working, but be aware that could change in the future.

  1. Download the attached Javascript File (If you cannot download for browser security reasons, you may copy and paste the code into a .js file from github. Minified Script. Non-minified Script.)
  2. Edit the File in a text editor
    • You'll need to customize line 3 (if using the minified version), or line 168 (non-minimized) with your tracking id number. Updated
    • //Working as of Aug 28, 2019
      function removeStorage(e){try{localStorage.removeItem(e),localStorage.removeItem(e+"_expiresIn")}catch(t){return console.log("removeStorage: Error removing key ["+e+"] from localStorage: "+JSON.stringify(t)),!1}return!0}function getStorage(e){var,o=localStorage.getItem(e+"_expiresIn");if(null==o&&(o=0),o<t)return removeStorage(e),null;try{return localStorage.getItem(e)}catch(t){return console.log("getStorage: Error reading key ["+e+"] from localStorage: "+JSON.stringify(t)),null}}function setStorage(e,t,o){o=null==o?86400:Math.abs(o);var*o;try{localStorage.setItem(e,t),localStorage.setItem(e+"_expiresIn",s)}catch(t){return console.log("setStorage: Error setting key ["+e+"] in localStorage: "+JSON.stringify(t)),!1}return!0}async function coursesRequest(e){let t=await fetch("/api/v1/users/self/courses?per_page=100"),o=await t.text();o=o.substr(9),o=JSON.parse(o);var s=JSON.stringify(o);return setStorage("ga_enrollments",s,null),parseCourses(e,s)}function parseCourses(e,t){if(null!=t){let s=JSON.parse(t);for(var o=0;o<s.length;o++)if(s[o].id==e)return s[o]}return null}function gaCourseDimensions(e){custom_ga("set","dimension4",,custom_ga("set","dimension5",,custom_ga("set","dimension6",e.account_id),custom_ga("set","dimension7",e.enrollment_term_id),custom_ga("set","dimension8",e.enrollments[0].type),custom_ga("send","pageview")}function googleAnalyticsCode(e){var t,o,s,n;if(custom_ga("create",e,"auto"),t=ENV.current_user_id,o=ENV.current_user_roles,custom_ga("set","userId",t),custom_ga("set","dimension1",t),custom_ga("set","dimension3",o),n=window.location.pathname.match(/\/courses\/(\d+)/)){n=n[1],s=0;try{let e=getStorage("ga_enrollments");if(null!=e){var r=parseCourses(n,e);null===r?coursesRequest(n).then(e=>{null===e?(custom_ga("set","dimension4",n),custom_ga("send","pageview")):gaCourseDimensions(e)}):gaCourseDimensions(r)}else coursesRequest(n).then(e=>{null===e?(custom_ga("set","dimension4",n),custom_ga("send","pageview")):gaCourseDimensions(e)})}catch(e){if((s+=1)>5)return custom_ga("set","dimension4",n),void custom_ga("send","pageview")}}else custom_ga("send","pageview")}!function(e,t,o,s,n,r,a){e.GoogleAnalyticsObject=n,e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)},e[n].l=1*new Date,r=t.createElement(o),a=t.getElementsByTagName(o)[0],r.async=1,r.src="",a.parentNode.insertBefore(r,a)}(window,document,"script",0,"custom_ga");
      googleAnalyticsCode("UA-12345678-1"); // customize google analytics tracking number here‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
  3. Save the javascript file after making changes
  4. Upload the javascript file into your institution's Theme Editor
  5. Navigate back to Google Analytics and view real-time data to see if it is tracking real-time users on your account. Know that you may have to wait for 15 minutes or so to be able to see custom dimension data.

Build Dashboards & Reports in Google Analytics

  1. You may wish to get started by downloading the following dashboards:
  2. Build your own and once you get it the way you want, share the template URL in the comments on this document!

Embedded Custom Javascript File

There were issues with people copying the embedded Javascript. Please view the scripts on Github.

Changes Made (May 31, 2019) New

The updated script has undergone significant change. Below are some highlights of what the updated script does. The updated script is mostly backwards compatible with the previous version.

General Changes

  • Updated to remove any jQuery dependencies. Modern javascript is being used (may not work on Internet explorer). This means that API calls are now asynchronous and non-blocking. Improves performance.
  • Fixed a bug that meant some pageviews were never sent.
  • Added a timeout if API requests fail to avoid server spamming
  • Added support for Google Analytics User-ID tracking
  • Altered API Endpoint & Data Caching
    • Instead of pulling the course information (/api/v1/course/:course_id), the script pulls a user's courses ("/api/v1/users/self/courses?per_page=100") which includes an enrollment object and caches the returned value into local storage. The associated enrollment object allows us to set the "Canvas Course Role" dimension. Caching the data should also result in significantly better performance due to reduced API calls. If a course does not appear in the user's course list just the course_id and user dimensions will be sent (should only be for Admins and public courses).  Also it will only pull the first 100 enrollments for a user (let me know if you need support for pagination with the revised endpoint).

Dimension Changes

  • Canvas User RoleUpdated
    • Instead of filtering for a best match of a user's roles and only returning 1 value this is now a comma separated array of all of a user's roles. When filtering on this value, look use something like "contains" & "student" to get any users with a role of student. The data is still pulled from environmental variables. You should be able to build better Audience Segments from this data. (ie: Students should only have user, student, and maybe ta roles).
  • Canvas Term ID New
    • This can be a valuable filtering tool as much of Canvas built in reports filter on terms
  • Canvas Course Role New
    • By altering the way the script queries the course data, we are able to now capture the exact role the user has in a course. If a user has multiple user roles in a course, the value assigned to the pageview will always be the first role in the array. This should be a very useful dimension for building reports and analyzing course usage. If you think capturing all user roles will be helpful, let me know in the comments.
Community Member

Ooooh yeah! I've been waiting for this!‌ help me set this up once long ago, but it fell by the wayside in the switch to new ui‌. I think there's a lot here we didn't have set up though. Your documentation of dimensions and dashboards is shaping up fabulously. I'm going to get this all set up again in preparation for CanvasCon USF: Using Google Analytics to Understand Canvas Usage

Community Member

It's working. Those custom dimensions were key! I can finally see some relevant data like their name, ID, and course.

EDIT: That first dashboard sucked. Here's a much cooler dashboard and template link:

My Second dashboard template link 

226671_Screenshot 2017-04-07-edit.png

Here's my first dashboard template.


Community Member, these articles are kind of old, but they came up in some Google Analytics searches I was doing. I'm curious if you know how much is still relevant. The first one about applying a filter to protect from malicious data corruption was intriguing. 

Community Member

I'm going to try to document my travels through this on my blog. Here's the first post Journey Through Google Analytics: Part 1 (teaser: there are more pretty data visuals). 

Community Member‌ and anyone else following this, here's a few updates:

1) I've shared this document, your event, and my blog posts to the Big Data‌ space. Seems appropriate.

2) My Dashboard stuff lives (and updates are planned to live) at JtGA: Part 2 - Google Analytics Dashboards

3) My mind is just whirling...I've got a Part 3 planned for Reports, and I've posted a rundown of 24hr ruminations: JtGA: Part 2.1 - 24+ Hour Observations‌.

4) I'm not sure if I will be able to make it to your live event, but I am sure going to try. Meanwhile, feel free to use any of my stuff in any way you'd like for that session. Consider it Public Domain.

5) I discovered the Google Analytics app. I'm still unsure if it's useful for me.


awilliams, thanks for being so interested in this! The first article is a little misleading. Google Analytics is not in anymore danger of being hacked than other google services. What can happen is that someone can take your tracking ID and theoretically feed it false data. If people want to follow the instructions in the article to set up a filter so it limits data only from their school site, they can do that, but that's really all it is, a filter. 


I've updated the original article to include a default dashboard that I built. I'd appreciate any feedback!

Learner II

Thanks‌ for sharing this and providing a demo of it at yesterday's Tampa CanvasCon!

Surveyor‌ Thank you for this post.   I have a question that is born out of my ignorance.  Doesn't this break FERPA?  We don't have a contract with Google and I believe they keep and use any data mined through Google Analytics.    Is this true or am I mistaken?   Now that I think about it, what about the information mined through their LTIs?


I don't claim to be a FERPA expert, but my understanding of Google services from their site is:

Google processes your data to fulfill our contractual obligation to deliver our services. Google’s customers own their data, not Google. The data that companies, schools and students put into our systems is theirs. Google does not sell your data to third parties. Google offers our customers a detailed Data Processing Amendment that describes our commitment to protecting your data.

Passage Taken from - Transparency - Google Cloud Help 

Then inside of Google Analytics, you can configure your account's data sharing settings:


And lastly, if you are still concerned, you should always be able to use the script without capturing the user name, in which case the data would be completely anonymous as the id numbers we are capturing are internal Canvas ID's (meaning someone would have to be a Canvas Admin to see user details). 

  • Delete the code on line 39 of the sample script if you'd like to remove the sending of usernames to Canvas.
    • 227768_pastedImage_9.png
    • If you do this, you may still wish to create a the custom dimension so shared dashboards and reports do not have to be refactored. 

Hope that helps!


I thank you, kind sir! This gives me the ammunition I need to sell Google Analytics to my boss.   Data!, Oh, the power is mine (insert maniacal laugh)!


Well, I spoke too soon on my last comment.   I don't think we qualify for the terms listed as we have no agreement with Google. I guess we need to discuss this further at my campus.   Even with the data sharing safeguard, Google is not contractually obligated to abide by those setting unless a contract is in place.   That is how I am reading it, but my lawyer speak is limited.

"The Customer agreeing to these terms (“Customer”) and Google Inc., Google Ireland Limited, Google Commerce Limited, Google Asia Pacific Pte. Ltd., or Google Australia Pty Ltd (as applicable, “Google”) have entered into a G Suite Agreement, G Suite via Reseller Agreement, G Suite for Education Agreement, G Suite for Education via Reseller Agreement, Google Apps for Work Agreement, Google Apps Enterprise Agreement, Google Apps for Business Agreement, Google Apps for Work via Reseller Agreement, Google Apps Enterprise via Reseller Agreement, Google Apps for Business via Reseller Agreement, Google Apps for Education Agreement or Google Apps for Education via Reseller Agreement, as applicable (as amended to date, the "G Suite Agreement"). This amendment (the “Data Processing Amendment”) is entered into by Customer and Google as of the Amendment Effective Date and amends the G Suite Agreement"

Community Member, it looks like it's a violation of Google's TOS. #7 of Google Analytics Terms of Service - Analytics Help 


It does look like passing names is a violation. I'll go ahead and remove the passing of names to Google Analytics. That should solve that problem, unless I'm missing something?

Community Member

That's correct. Sorry, I should have been more specific. I've done the same, removed names from the dimensions in GA and the lines in the JS and updated my reports and dashboards. Chris Ward was nice enough to point me to a blog post that linked to a Chrome Extension that solves this problem locally. You create your own local CSV which it uses to then show you PII on top of GA. I haven't got it fully working yet but here it is: PII Viewer for Google Analytics - Chrome Web Store 


Quick and easy to setup! Had new data rolling in within minutes.  Can wait for the other links and more information to be shared.


REAL-TIME Overview: Right now 0

I followed everything step by step an not seeing any results. The only difference I saw was in the dimensions Archived vs. Archived Value (inactive).  With >160,000 students, I'm 100% sure there has been 0 active users since installing yesterday.


  • Is Tracking ID the only customization to the .js file to be loaded into the theme editor?
  • Does User-ID need to be enabled under .js Tracking Info?


Community Member

I set this up in our test instance today and had some data appearing for about 5 minutes and then nothing at all since that time.  Not sure where to start investigating at this point and any feedback would be appreciated!

Community Member

Disregard my comment. Data has started coming in again.  


Sorry for not responding sooner Patrick! I'd double check that your tracking ID is correct, and you do not need to collect the user_id. Have you had any luck since you posted this?


Still no luck and I've checked the tracking ID several times.

Account: Data Sharing Settings are all unchecked, Data Processing Amendment for this account has not been accepted.

Property: Got the Tracking ID (UA-********-1), URL has https, custom dimensions added (screenshot has archived value inactive & js file has archived - not sure if that impacts anything other than the dashboards)

View: URL has https

Everything else is right out of the box.

The only custom JS in the Theme Editor is what you provided and the changed Tracking ID.

Any chance our network team is blocking something needed? I use Google Analytics on some of our support sites and that works fine.

We will be getting Canvas Data up an running soon on a local server so that may have to be my data bread and butter. Thanks for checking in regardless.


So today must be my lucky day. Gave it another shot and everything is working fabulous. Thanks!

Community Member

Just wanted to say thanks for this information. I was able to setup GA on our production instance and have started getting data.  Here are a a couple of dashboards that I'd like to share. They are essentially the standard widgets but the data is filtered for students and instructors.  Our sample size is pretty low over the summer and I'm looking forward to seeing how the data in the dashboards changes in the fall.  

Student Data Dashboard

Instructor Data Dashboard

The next steps I'd like to figure out involves using GA to complement (or possibly replace) the overwhelming requests table in Canvas Data. 

Community Member

Thank you everyone for the information! This is great! I'm very new to Google Analytics though. I have everything setup per the above document however, the only thing that seems to be working is the active users, and the pageviews in the last 30 minutes. Does it take 24 hours for the rest to populate? I also see there is a widget for sessions by browser, but there isn't any information. With the above JS, does it automatically pull that information in? Have I done something wrong? Is it actually working?

screenshot of dashboard

Community Member

I ran into that scenario as well when implementing GA.  I would imagine coming back from the weekend that you should have more data displaying in GA. It seems some of the custom fields/values take about 24 hours worth of data to accumulate before populating fields on dashboards.  If you don't, the first thing I would check would be the code in the custom js that is in the Canvas theme.  When editing our custom js file one of the text editors left a long string of junk characters at the end of the file.  It seems that GA code has some sensitivity to white spaces and extra characters.  

Good luck with GA!

Community Member

Can anyone tell me, when I create the analytics account, in Property Settings, Default URL, should I be using our DNS name (vanity URL) or our <DOMAIN> address?  Support told me "the vanity would be preferred actually as it appears all of the bulk of requests are going to be made through there". The instructions above say to use to use our Canvas url in the website url field (eg:


We use the even though we use CAS for authentication and it works great!


If we install this on production Canvas is it copied to the Test Server every three weeks?  If so is the data display for both Prod. and Test servers?  Do we need to filter on the Analytics side to only get the production data?

Community Member

That's a good question.  I tested the Google Analytics code on the global javascript first to make sure Canvas was happy with it on Test system, but can't remember if it actually caused data to start streaming in from the test system.  Our test system isn't used very much so I wasn't worried about it affecting the numbers in a significant way since only a small group of users know about or use the test system.  

Surveyor II

I got the link to this page from a webinar I was recommended to attend by our Customer Success Manager, called "Learning Analytics". 

I've followed the directions on this page and no analytics show up. I've read numerous other forums and checked countless pages, settings, code, etc. I'm going on about 2 and half weeks of troubleshooting and trying various changes in the script - nothing will get me data. 

I keep seeing an error labeled: No HTTP response detected. I have followed the instructions, removed the entire JS - waited a couple days, uploaded again. 

Any suggestions are greatly appreciated. 

Community Member

- Check there's no global filter excluding any IP addresses you're trying to visit

- Put the GA code at the top of your javascript file, before anything else except comments. 

Both made a difference to me, and I've got it running in about an hour.

Surveyor II

I've moved the GA code to the top. We dont know of any global filters - unless our internal filters are blocking tracking (iBoss?)

Here is my code if anyone is willing to look at it - I have made no modifications to this except entering our own GA code and moving the code to the top as suggested. 

google_analytics_new v2.js - Google Drive  

Community Member

The code you've provided looks ok to me.  I did have an issue when editing our custom javascript file where it had been previously saved in a text editor that added a bunch of junk characters at the end of the file.  It may be worth a quick check to open the javascript file and check to make sure there are no extra junk characters especially if you edited/created the javascript file with an editor like Word or Google Docs.  

Surveyor II

Thanks. I've used PS Pad for most of my HTML and other scripting. I've opened the JS file in other editors and don't see extra characters at the end (DreamWeaver, Notepad, Word). 

Just to double check, in GA, the most that I had to do was create the dimensions? 

Canvas Google Analytics - Google Docs 

Community Member

I meant global filters as in the filters in GA which prevent traffic from your own IP address being counted in the data, so if you're a web developer for example, your own employees don't affect the stats by doing their day to day work etc. 

If you're seeing nothing at all this is an unlikely issue especially if you allow off-site visitation to Canvas, but if there's a filter there that excludes your own IP address, you won't see your own visits showing up in real time or any other data.

Community Member

I have a question.  If we have multiple themes for different schools based on their colors, do I need to apply the js file to each theme or only the one used for the login and the root account?  Thanks!


Just the root account

Community Member

Has anyone added the Google Analytics JavaScript to the theme for the Mobile app?  I just have it running on the desktop application and some our student workers mentioned that they use the app way more than the desktop app.  I hadn't given the Mobile app JS a try since it wasn't mentioned in the directions above or any follow-up posts.  Was hoping to get a bit of feedback before leaping and adding the JS file for the Mobile app.


I'm having trouble matching up the Canvas User ID to my Canvas uses - As an example, I implemented @Ryan Sims Instructor Data Dashboard however for the “Top 10 Instructor Users” the Canvas ID does not match the sis_user_id, user_id or canvas_id when I try to map it to the user outside of Google Analytics. 

Community Member


Hmm. Maybe double check the Custom Definitions/Custom Dimensions settings in the Property for the site you are tracking?  Are you getting data for the other custom dimensions?


Yes, I am successfully getting data for the other custom dimensions.  


Okay. I figured it out —

If i type in  I can figure out who the user is — although it’s still interesting that the User ID, is different from that in pseudonym flat files.

Community Member


Community Member, Do you have any further information on the mobile app with Google Analytics?  We're an iPad 1:1 district.  While Google Analytics seems to be working thanks to the clear instructions from awilliams, and the Community, it will be of limited use without incorporating the app data.  I added the js file to both the browser and mobile theme editors.  It's definitely not tracking app users.  I can't be sure about app page views, but don't think these are being tracked either.  Wonder if you had better luck?  If so, did you need to change the js file? 

So close! But out of 15k accounts, I'm only registering 75-80 active users - might be right for the teacher laptops. I haven't implemented tag manager yet.  Wonder if that would make a difference for the app?

Community Member


I applied the Google Tracking Code in the JS for the mobile app but didn't notice any appreciable difference in the data gathered.  There may have been a slight up tick in tablet traffic noted, but nothing significant.  We still capture quite a bit of iPad traffic but it is hard to determine if it is a user using a browser or using the actual app.  Wish I had a better update to provide.  I'll probably look into this a bit more and be sure to share if I make any progress.

Community Member

Ryan, I wonder if this topic deserves its own discussion thread? I noticed a previous question post at this link Google analytics for Canvas mobile app, but that post was from 2016.

Update 11/27/17 - I asked our CSM to check with the mobile team to find out if hits from the Canvas apps could register in Google Analytics.  I didn't want to pursue if it wasn't possible.  I heard back today that the app data doesn't show up for Google Analytics.  "The app operates on the API layer, which makes it hard for us to even track data." 

I'm disappointed.  I got just far enough to see the possibilities and was excited!

Community Member

We recently got our Google Analytics turned on for Canvas. We have the custom dimensions configured, but I'm wondering if there is a custom dimension for the Course Section ID. Has anyone worked with that? 


Greetings, all!

I wanted to see if any of y'all had issues with the rest of your javascript "breaking" when you add your GA code. We have some custom menu icons added (thanks to the great‌ over at Help With Custom Menu Icons and Script), and when I add the GA code my menu items break. I see where said to put the GA code at the top of my .js code, but it doesn't matter where it is in my document - menu items break. Does anyone happen to have experience with this? Before we can begin to tackle the google side, we have to ensure the other scripts don't break!



Never mind. I got it to work. Kept on pouring over my combined script and got things to work. Data started to pour in within minutes - and our custom icons stayed. Thanks!

Community Member

I am ready to add the JS file to my Theme editor. However, there is already a custom JS file there. Do I apoend the new JS to this file? I do not want to overwrite what is there.  The content of the GLOBAL JS file that is there had to do with Canvabadges, some custom neus, etc.

Any advice? I would be happy to share the JS file so you can see it.