Skip navigation
All Places > Canvas Admins > Blog
3 4 5 6 7 Previous Next

Canvas Admins

92 posts


Anyone supporting Canvas users for awhile has discovered the need to frequently troubleshoot issues in response to vague statements like, "Things don't look right" or "I can't see it." Therefore, less experienced Canvas admins might find this a useful tip!

Suggested Troubleshooting

Please use these alt. lyrics to sing along to Johnny Nash's I Can See Clearly Now (1972):

I can see clearly now, I've cleared my cache,

I can see all the stuff that had gone away.

Gone are the dark clouds that had me blind,

It's gonna be a bright, bright, bright tech-integrated day!


The latest example of the need to clear the browser cache was just yesterday when I heard from multiple users that their Mastery Path settings had vanished. Upon checking, mine too! Rather than despair, however, a song entered my head . . .


I can see clearly now, I've cleared my cache . . .

Information about clearing the cache in a variety of browsers can be found here.

The Payoff

When things aren't looking quite right in Canvas, I've found that clearing the browser cache very often pays immediate dividends for the end user. Why wait up to 24 hours to have Canvas Support suggest the same thing as their first line of troubleshooting?


Like the song says, It's gonna be a bright, bright, bright tech-integrated day!

Priority: New Quizzes: General Availability The specified item was not found.

I want to chime in (again) about the issue of question/quiz interoperability particularly as it relates to bulk import into Canvas.


The original blog, Batch Uploading Quiz Questions with Respondus, and its comments are mostly fro 2015. In the meantime, Canvas has expanded its question types. It will continue doing this in its quizzes.next_new quizzes.next_phase1 quizzes.next_phase2 version, soon to enter beta. The information in the blog about Respondus 4 is somewhat outdated. Because it's the only game in town as a standalone QTI generator, the laudatory remarks about it are, IMO, misleading.


I've used Respondus 4 quite extensively to duplicate the built-in bulk import features of Blackboard LMS. It's clear that the folks at Respondus haven't updated and refreshed its design or function in many years. Editing windows and windoids are not resizable, making for a cumbersome, finger-clicker tiring, eye-straining experience.


Functionally, there shouldn't be too much of a difference between publishing quizzes and question banks, but there is. Canvas's current inability to shuffle questions (as opposed to question distractors) forces developers who are planning backwards from the quiz level to create Question Groups from which quizzes will draw questions randomly. (Rumor has it this feature will be included in Quizzes.Next.) Respondus 4 could save time with the choice between quiz- and bank-publication. Unfortunately, bank questions lose their image reference links, unlike the quiz publish function which preserves them.


Attempting to pre-format question stems using HTML tags and inline CSS is a punishing exercise. The simplest example to illustrate this is including <p> tags to put images on their own line separate from the text that precedes and follows it. This very simple exercise requires opening the HTML windoid, pasting the code, saving to close the windoid, then saving the question edits before proceeding to the next question. Through trial and error, I discovered that the tag-enclosed text of the stem must also be pasted in the HTML windoid otherwise it won't export properly.


Question Editing in Respondus 4


As a result, Respondus 4 is the type of indispensable application one loves to hate. I don't even want to surmise why the company has chosen to ignore these flaws, or redefine them as features. I wish Instructure would flesh out the import API it uses in Canvas to create an reliable, robust, and easy-to-use import function, leap-frogging over what Blackboard implemented from many versions ago. With a more robust API, teacher/designers/developers would only need to format a TEXT or CSV file conforming to a data map Canvas defines. The map would permit the following fields: question type, question stem, distractors, correct answer, answer feedback, and frequently used question feature toggles (e.g., distractor shuffle). The map should also accommodate image embedding, similar to what Respondus requires (images need to be in same folder as the bulk question text file).


This commonly used routine would be a great feature family update, and what I referred to in the idea currently up for vote: Strengthen Canvas Import Ability with QTI Files.


Thanks to Chris Hofer's Blog for the progenitor to this post.


In our school district, I strive to limit global announcements to one-per-month and use them exclusively for Canvas-related tips, resources, and learning opportunities. Here's a recent example:


An image of the April Announcement provided to users in Arlington ISD. The image shows green spring leaves, a faded out Super Canvas Panda, and text reading 'Attention: April FYI and Tips'.


These announcements auto-open and close using the availability dates provided to account admins when creating or editing global announcements in Canvas.


There's just one problem, however. Many teacher users click the 'X' by accident or before reading the announcement's contents when it appears on their Canvas Dashboard. How can they retrieve or regain access to that announcement if it has disappeared?


Suggested Workaround

In Arlington ISD, I've added a publicly-visible course titled 'Global Announcements Archive' as a custom link in our Canvas Help Menu. It looks like this:


An image showing Arlington ISD's help menu in Canvas. One link states, "Global Announcements Archive. Refer back to previous Canvas announcements"


When teacher users click on the link, they navigate to a publicly visible Canvas course where we replicate each announcement as a Content Page within a Module. As you'll see, the course's home page is set to Modules.


An image showing the appearance of the publicly-visible course that contains a module for all announcements made during the '16-'17 school year. The announcements are listed chronologically and there is one per month.


The Payoff

The primary benefit of creating and maintaining a Global Announcements Archive is that I can direct any user to it in those instances in which they have overlooked, ignored, or accidentally removed an announcement on their Dashboard.


Additionally, it's a useful way for me to revisit past efforts to communicate important information to our Canvas users. I look forward to being able to revisit the archive next school year so as to avoid the need to completely reinvent the wheel in regard to the resources we provide at the beginning of a new term!


If you haven't thought about the potential payoff of creating an Announcements Archive in Canvas, give it some thought. I've definitely found it to be a worthwhile resource to provide to our users! 

In this blog, I'll explain how our College uses a custom "Viewer" role in conjunction with "master" courses. This blog expands on part of a Twitter chat conversation I hosted on Tuesday, February 14, 2017 called #CanvasChat: Managing Masters. But first, some background...


At MPTC, my team (Instructional Technology) gets approved course curriculum from our Instructional Designer/Curriculum department to build into the LMS. We take the course curriculum built in WIDS (an online curriculum building tool) and put it into the LMS. For the most part, our team builds the curriculum for our faculty and adjuncts so it is ready for them to teach at the beginning of the semester. Most of our instructors do not build their own curriculum into the LMS themselves. One of the reasons for this is to have a consistent "look" and "feel" for the courses that we that students have a general idea of where they need to go to access parts of their course. If instructors build content on their own, there is high chance that course "A" will look different than course "B", and students would have to figure out where to navigate around the course. We wanted to avoid that. Additionally, we found that this consistency also has helped our retention rates.


When we moved to Canvas, we wanted to mimic a similar setup we had with our previous LMS, Pearson eCollege’s LearningStudio, by way of Canvas Permissions. We decided to create a custom role (How do I create course-level roles in an account?) called Viewer. This new role was based on the "Teacher" Base Type. (This was the only way we found that instructors could import content from a "master" course.) For our Viewer custom role, we turned off almost all permissions, but we kept the following turned on:


  • Create student collaborations
  • Create web conferences
  • Moderate Grades
  • Post to discussions
  • See the list of users
  • Send messages to individual course members
  • View announcements
  • View discussions


Some of these permissions might not really apply, but that's what we've got set right now. The custom Viewer role can only view a course. Instructors assigned this role in a “master’ course cannot make any edits to the course content.


We work with our Deans and their Administrative Assistants to determine who gets access to “master” courses in Canvas. In general, we typically have one full-time faculty member (sometimes two or three) who is the person responsible for keeping a course up-to-date in Canvas. This person is assigned the Teacher role in the “master” course. Then, other faculty and adjuncts in the same program area are enrolled in the “master” course with the Viewer role. This allows for collaboration among the team. Based on student and instructor feedback, an instructor with Viewer rights can talk with the instructor who maintains the “master” to make any suggested or needed changes to the course.


If you choose to do something similar at your school/institution, be aware of one minor thing. When instructors are enrolled in "master" courses and then look at their "Courses" >> "All Courses" screen, they will currently NOT see the custom name that was created by the admin. Instead, they will see Teacher listed under the Enrolled as column. I submitted a Feature Idea about this issue in April 2015, but it's been put on Product Radar (New Ideation Stage: Product Radar): Custom Role Name on "View All or Customize" screen.

Each Monday I post a Global Announcement listing the up-coming CanvasLIVE sessions that are happening for that week.  I have noticed over the past few weeks that several CanvasLIVE events are being streamed over YouTube.  This got me thinking yesterday...  Can I embed a streaming CanvasLIVE event using the YouTube LTI in a Global Announcement?  The answer...yes!


(This may work for other non-YouTube websites...though I've never YMMV.)


  1. Make sure the YouTube LTI is added at the account level of your Canvas instance.
  2. Go to a CanvasLIVE event page such as Google LTI Series: Accessing Your Assets 
  3. Navigate to the YouTube link given for the event, and then highlight/copy the title.
  4. When creating your Global Announcement in the back-end admin pages of Canvas, select the YouTube button in the RCE, and paste in the YouTube title (or I believe you can even paste in the YouTube URL) in the search box.
  5. Embed the YouTube video on your announcement.


You may want to include a note along with your announcement that users will need to click on the "Play" button for the video in order to start watching.  Also, after the session is over, the recordings are immediately available via the same YouTube URL.  Since I just started trying this yesterday, I set the global announcement to display five minutes prior to the start of the CanvasLIVE session and then end 15 minutes after the scheduled time ... in case the session runs over the scheduled time.

I have seen several Canvas admins who love the "access dates" on terms, but are hesitant to use them because they have MANY terms that would need to be adjusted.  Currently, it must be done through the UI, one-at-a-time and can be quite time consuming.  It can not be done through a CSV upload, nor is it documented in the API.


Well, I whipped up a Google Spreadsheet to help Canvas admins create the API to change these access dates. It's not fancy. It simply creates the API call that you can then copy and paste into a MAC or Linux terminal. It can also be used in a Windows command prompt if you install cURL.


Feel free to critique, improve, re-share etc.  If you decide to automate this more, I'd appreciate it if you would share a link in the comments below so others can benefit from this work, too.


Here is my Google Spreadsheet.


I hope this helps!


Keep Learning!


Recently a department asked me for a solution to their grading scheme.  In this case the department has multiple criteria for passing a course.  The first criteria is that you must have a passing grade for your course work, which the Canvas grade book handles very well.


However, there is a requirement that a student score at least (n) points on the final exam.  If the student scores (n-1) points or less, the student fails the course, regardless of the cumulative grade.  There are other requirements surrounding clinical hours, labs, etc.  So, even if the cumulative average of the course work is passing, a sub-standard grade in any one of the individual categories of evaluation results in an F.  The Canvas grade book does not allow us to create multi-layered grading schemes like this.


I was told - "if only we could override the final grade, we would be fine"

This article will give you an overview of the solution that I came up with.


Step By Step Walk Through

This solution uses weighted assignment groups to create a custom grade override.

If you are not familiar with weighted assignment groups, you might want to read through the basics:


Step 1:  Create assignment groups that represent your logical units of work.

Common assignment groups that I see are "Homework", "Quizzes", "Tests", "Final Project", "Papers", etc.

You could have only a single group, or multiple groups.  Either way, the group(s) should add up to 100% of the final grade.

If the student completes all of their work, and there is no override to their final grade, the scores from these groups is where the final grade will be derived from.


All of your normal course work should be placed in the appropriate weighted assignment groups to match the grading scheme that you have defined in your syllabus.



Step 2:  Create the Override Assignment Group

Adjusting the final grade can be done by creating an additional Assignment Group.

Decide how much you would like to be able to adjust the grade by.  For the purposes of this explanation, I'll use easy math.

If I want to adjust the final grade by 10%, I would create an additional assignment group worth 10%.

If I want to adjust by as much as 20%, I would create an additional assignment group worth 20%.

....and so on.


For a standard 10 point grading scheme, 50% is easily an F.  I would like to be able to adjust a student score by as much as 50% if they fail any category of assessment.  So I'm going to create a new assignment group and call it "Final Grade Adjustment", and make that assignment group worth 50% of the course grade.  Now my Assignment Groups settings will look like this:



Step 3:  Create the Override Assignment

Now I need an assignment where I can assign the points to actually override the grade.

In this example, I want to adjust the grade by as much as 50%.

If we are working on a 10 point scale, and I am going to adjust in increments of letter grades (10% == 1 letter grade), then I am going to create an assignment worth 5 points.

When I create the assignment, I want to include a description that re-enforces the rules that were clearly defined in my syllabus.  The student will have a clear definition of why the final grade might be adjusted.  Here is what my assignment definition might look like:


Notice in the screen shot that I have given a description of what conditions qualify for the adjustment.

  • I have assigned a point value of (5) points.
  • I have placed the assignment in the "Final Grade Adjustment" assignment group.
  • I have specified "No Submission", I am simply going to enter a point value


My Assignment Groups view will now look like the following:



Why 5 points?

We are leveraging the "weight" of the assignment group.  I want (1) point to represent 10% of the final grade, or one letter grade

  • If I want to drop the final grade by a single letter grade, I would assign a point value of (-1) point, the student has scored -20% of the points possible, and will receive -10% of the group weight (10% is equivalent to 1 letter grade)
  • If I want to drop the final grade by two letter grades, I would assign a point value of (-2) points, the student has scored -40% of the points possible, and will receive -20% of the group weight (20% is equivalent to 2 letter grades)
  • If I want to drop the final grade by three letter grades, I would assign a point value of  (-3) points, the student has scored -60% of the points possible, and will receive -30% of the group weight (30% is equivalent to 3 letter grades)
  • If I want to drop the final grade by four letter grades, I would assign a point value of (-4) points, the student has scored -80% of the points possible, and will receive -40% of the group weight (40% is equivalent to 4 letter grades)
  • If I want to drop the final grade by 5 letter grades, I would assign a point value of (-5) points, the student has scored -100% of the points possible, and will receive the full -50% weight of the group (50% is a full 5 letter grades).

Using the approach, (1) point represent a full letter grade on a 10 point scale.

Also notice that this allows me to adjust a final grade in either direction.  Negative points deduct a letter grade, but positive points increase the letter grade.


Step 4:  Test results in your gradebook

Looking at the gradebook you should see the assignment listed, as well as the assignment group.

To get started, I will use Student 1 who has achieved a perfect score on all of his assignments giving him 100% for a final grade.  This will allow for easy demonstration of how the penalty is applied:


To remove one full letter grade for Student 1, I will assign (-1) points to the "Final Adjustment" assignment.

The result is a (-20%) in the weighted "Final Grade Adjustment" column, which forces the final grade to a 90% B

  • 20% of 50% is 10% = 1 letter grade


To remove two full letter grades for Student 1, I will assign (-2) points to the "Final Adjustment" assignment.

The result is a (-40%) in the "Final Grade Adjustment" column, which forces the final grade to 80% B

  • 2 points is 40% of the possible 5, 40% of 50% is 20% = 2 letter grades


And so on, you can test with the other point values in your gradebook to verify the results.


Leaving Comments

I have strongly recommended that faculty leave comments on points awarded to the "Final Adjustment" score, so students have a clear understanding of why their final grade was adjusted.  This is of particular importance if the grade is dropped.  If you are not familiar with how to leave a comment on a score, take a look at this article:


Important Observation

In the screen shots for Step 4 you will notice that I have not awarded any points to Student 2.

Student 2 has only completed the "Class Participation" assignments so far, and has received a 75%, or a C, to date.

I have not awarded any points to the "Final Adjustment" assignment, and there is no adjustment to that final grade yet.


Keep in mind, that with this strategy the course is worth 150%.

It is worth noting that if you do not award points to the other weighted assighment groups, this approach will break.

It is critical that ALL of your grading be complete before you award any points to the "Final Adjustment".

The 50% weight of the "Final Grade Adjustment" group applies to the entire course.

Make sure you test this scenario to fully understand the behavior.

See this screen shot to see how a (0) score in "Final Adjustment" affects Student 2:

If Student 2 has been awarded 100% of their points so far, why is their grade an F?

It is related to the group weights.

Make sure you understand the behavior of group weights.


Canvas has announce that there will be a "grade override" feature coming, but there is no expected release date.

Hopefully this will provide a possible solution in the mean time.



This strategy is easily modified to allow granular control over the final grade.  In this document I created a strategy that equated (1) point to 10% of the final grade.  If I had made my assignment worth 50 points, then I would have made a 1-to1 relationship, where (1) point would be equivalent to 1% of the final grade.


The strategy that I'm using works for a grade adjustment in both directions: as a penalty, as well as a bonus.

By using negative point values, I'm taking away from the final grade.  If I used positive point values I would be adding to the final grade.  To look at this from the perspective of giving a bonus, or giving extra credit, Stefanie Sanders has posted a great article that will help:


Canvas is working on a grade override function, which has been greatly anticipated by the Community.

However, I like the approach used here, as it provides a method of clearly defining WHY the adjustment is being made (i.e. the description given in the assignment definition that reinforces the syllabus), and allows the instructor to leave comments for each individual student to further clarify why their grade has been adjusted.  I feel this is very important for the student.

Update: November 18, 2017

Canvas has provided their own solution!



The solution for Canvas is from the list of all pages, click on the admin cog next to the course that is currently the front page and choose "Remove as Front Page".


The solution I offered in 2016 was to go to the page itself and then deselect it as the front page. The solution described in this blog post still works, so I'm going to leave it out there in case people can learn from it, but you probably should disable it and just use the Canvas solution.


Original Post: August 28, 2016

This is going to get lengthy - for those who are impatient, there are installation instructions and a video at the bottom.


Every now and then someone wants to remove the front page designation from their course. In fact, another request just came in a couple of days ago: Delete Homepage. They don't actually want to delete the home page, they just want to tell Canvas that there shouldn't be a home page, which in Canvas parlance is called the front page, which may or may not be what a user gets when they click on the Home navigation link.


The Canvas guides tell you How do I set a Front Page in a course?  but they don't tell you how to unset a front page for a course, so asking how to do this is a reasonable question.


Typically when this request is made, there is a back-and-forth discussion about how it's not really as big of deal as it seems. The point is made that it is easy to change the default view of the page from within the web interface so that the page is not shown when people hit the Home button. The return conversations points out that changing the default view still keeps a page with the "Front Page" designation and that's what is shown when users click on the Pages navigation item, which means that the list of all pages is no longer shown, but requires an additional click to see the list. The rebuttal is that the list of Pages is worthless and so you shouldn't be using it. The original poster then asks why do we have the Pages page then, and the conversation goes on like this until someone gets tired and gives up.


But the problem still exists that once you've assigned a front page, there is nothing in the web interface that allows you to unassign it and get back to the list of pages as the default. There may actually be a use for having a list of pages, I named all of my notes for my summer course last year in a way that alphabetical ordering made sense, so I can see the point.


There was a lengthy discussion about it a year ago: Allow deselection of Front page status . Many people there said it was impossible, some offered hacks like recreating the course or rolling back the history on the page to a time when it wasn't the front page. And Matthew Libera presented a solution on September 9, 2015, that went mostly unheeded and definitely not understood. In fact, the only response to it was "??".


Fast forward a year and on August 12, 2016, Matthew made another post, with the same information, but this time included screen shots and instructions, and became the hero.


The problem is his solution required people to obtain an access token, load the Live API interface, and enter the access token and the specific information about the course. The approach is certainly not impossible, and Matthew does a good job explaining how to do it, but it not easy. Unfortunately, that means that many won't attempt it.


The trick he points out is to use the Update/Create Page endpoint of the Pages API. This inability to deselect a front page had thrown me for over a year until I ran into Matthew's post last week. The reason is because, to me, the Update/Create Front Page endpoint was the obvious place where you would set the status of the front page.


Except that the obvious place is not the correct place.The trick is to take the page that is the front page and tell it that it is no longer the front page. Then, since there is no more front page, Canvas displays the list of all pages instead and the problem is solved. You can't tell the front page it's not the front page by updating the front page. Like I said, it's not obvious.


Removing the front page status involves the PUT method with a payload of "wiki_page[front_page]=0" to the API. The URL used is exactly the same as the page you would see while you're viewing that page from within Canvas, except there is an /api/v1 squeezed in before the /courses.


This can be accomplished using the API or using REST clients that are available. If you already have an access token and do other things with the API, it's a fairly easy task to remove the front page status.


The problem comes when you don't use the API and don't already have an access token and don't have the technical skills to figure it out.


The good news is that you don't have to have an access token to access the API. You can access the API through the browser if you are logged into your Canvas instance. In fact, if your API call is a GET, you can just put the API endpoint into your browser's location window and get the information. There will be a while(1); at the beginning, but after that will be the results.


The first problem with that is that this removal process uses the PUT method and not the GET method, so that approach is out. Otherwise we would have a really simple solution that anyone who had permissions and was logged into Canvas through a browser could do.


The JavaScript code that loads with Canvas often makes calls to the API using all of the basic methods (GET, PUT, POST, and DELETE). The way it gets around this without an access token is by sending an X-CSRF-Token header with the request. Oversimplified, this token verifies that you are a legitimate user who should have access to the API. It's kind of like an access token, except it automatically comes with information sent from Canvas and changes frequently to make sure the request isn't a fake because someone was able to guess it.


I've written some user scripts before that make AJAX calls through the browser to obtain information. I used jQuery and it just kind of magically took care of the what needed taken care of, so I had never really given it much thought until today. Today, I tried writing a script without jQuery, using only JavaScript, and so I had to figure out all that stuff out by hand. I probably missed something and it's definitely not pretty, but in the end it works.


Here's what it does.

  • Checks to see that you're on a page that begins with /courses/*/pages/*. Those * are wildcards and require that there be something after the /pages in the URL, so it won't activate on the list of pages. It also won't activate on the page that you get when you click the Pages navigation link, which is called /wiki and not the name of the page itself.
  • Checks to make sure that the current page is set as the front page and that the user has the ability to manage the page. According to the Canvas Course Role Permissions document, managing a page is what's needed to set something as a front page, so I figured that was a good permission to use for deselecting a front page.
  • Waits for the page to display. Canvas has gone to including the contents of wiki pages completely within the ENV variable and then using JavaScript to display it on the page. That means that the page is not displayed as soon as the Document Object Model (DOM) is ready. You can tell this by viewing the source of the page in the browser and seeing there's very little there in the wiki_page_show portion. In lay terms, I can't add a link to remove the front page status because the place where I need to put the link isn't even there when my script starts running. So I have to wait until the information is displayed on the page. I use a MutationObserver to do that. It turns out that the first set of mutations to the element with id="wiki_page_show" is good enough, so I disconnect the mutation observer so it's not continuing to listen for changes to the page and then add the link to remove the front page status.
  • There is a link added to the bottom of the Admin Cog that says "Deselect Front Page" and it has the little Home icon before it so that it looks like the other links of Delete, which is disabled for the front page, and View Page History. This won't show up unless someone clicks on the Admin Cog for the page.
  • When the Deselect Front Page link is clicked, I obtain the URL of the page, insert the /api/v1 before the /course, find the _csrf_token from the list of cookies, and then make an AJAX call to the Create/update page endpoint. Once that call returns, I remove the little notice from the top of the page that says this page is the "Front Page" and the script is done.


Here is what right side normally looks like when you click on the Admin Cog.

Here is what the right side of the front page looks like when my script is running and you click on the Admin Cog:


You've decided that you would like to remove the front page status without having to obtain an access token, so what do you need to do? The steps may still be beyond the technical level of some users, but this is a place where Canvas Admins could load the script in their browser and then help out their faculty how want the front page removed. Here are the steps.

  1. Install a browser add-on: Greasemonkey for Firefox or Tampermonkey for Chrome/Safari. I've tested the script in Firefox, but I don't think there's anything special I did that would keep it from running in the other browsers. If there is, let me know.
  2. Install the Deselect Front Page user script.
  3. Click on the Pages navigation link and View All Pages. Note that the script will not run on the page that you get when you click on Pages. This is to keep it from running when it doesn't need to and also to get the URL of the page from the browser.
  4. Find the page that is indicated as "Front Page" in the list of pages and click on it.
  5. Click on the Admin Cog and choose "Deselect Front Page"


Here is a video showing you what you can expect.

Hi all,


I just found a way to place a form into our institution's website that helps our users search the Canvas help guides inside Jive (here's the info). It's a rather "brute force" method -- when users click "Search" on our institution's page:


A new browser tab appears with the Canvas Jive search results:



I limited the search results to "documents" -- this mostly narrows down search results to the help guides, but not completely. Anyone have ideas how I could narrow search results further?


Last but not least -- here is the code I'm using to embed the search bar on our site:


<form action="" method="get" target="_blank">

<input class="form-control" title="Enter a keyword or topic to search" name="q" type="text" />

<input type="hidden" name="type" value="document">

<button class="btn btn-default btn-lg" type="submit" value="Search">Search</button></form>


The class "form-control" has a bunch of formatting stuff that is specific to our institution's website. But of course you can use this class to style the search bar however works best for you! The button class is pulling from Bootstrap, which our institution uses to style our website.

In our Canvas instance, we've created a few dozen terms so far, mostly via integration with our SIS.  Each year we add several more, and the list is getting out of hand.  Further complicating matters is the fact that the terms are sorted in a seemingly random order.  Finding the specific term you're looking for in this long, out-of-order list can be tricky.


Fortunately, our naming convention places the year first, followed by the name (e.g. "2016 Summer"). If we could just have these lists sorted by the term label, things would be much easier to find.


So, I wrote some custom Javascript that can be added to your pages via the Canvas Theme Editor to do just that.  If you want to use this code in your own Canvas instance, you can download it from GitHub and customize as needed.


Here's how it works:


First, we define two functions -- one to sort the term select list on the "Courses in this account" pages, and one to sort the term table on the root account's terms page.


function sortTermDropdown(){

  var termSelect = $('select[name="enrollment_term_id"]');

  var selectedOption = $(termSelect).val();

  var termSelectList = $('option', termSelect);

  var newList = termSelectList.sort(function(a,b){

    return (a.label >= b.label) ? -1 : 1;





function sortTermTable(){

  var termRowList = $('table#terms tbody tr.term').get();

  var newList = termRowList.sort(function(a,b){

    var alabel = a.getElementsByClassName('name')[0].innerHTML;

    var blabel = b.getElementsByClassName('name')[0].innerHTML;

    return (alabel >= blabel) ? -1 : 1;





Next, we have some code that gets run when the page first loads that checks to see if either the term drop-down list or the term HTML table is present on the page, and calls the appropriate sort function.


$(document).ready(function() {

  if ($('select[name="enrollment_term_id"]').length > 0) {



  if ($('table#terms').length > 0) {





Since all of this javascript will be included on every page in our Canvas instance, the conditionals above allow us to only run the sort functions when necessary, reducing the chance for errors and minimizing the impact on pages that don't have any term lists on them.


Finally, we've chosen to have our terms sorted in descending order; because our labels begin with the year, this puts the most recent (and most frequently used) terms at the top of the list.  If your labels would be better sorted in ascending order, all you need to do is change the 'return' lines in each of the functions above, swapping the '1' and '-1' values.

Many thanks go out to Kenneth Larsen and the CIDI team at Utah State University, who built a fantastic Canvas Template Engine that make course creation a breeze!   However, there are many moving parts to get KennethWare 2.0 working inside of your Canvas instance. In an effort to make the installation easier for the Canvas community, I created this general discussion and process guide.

People Needs:

  1. A Canvas Administrator.
  2. A Systems Admin (or some really clever person who can create and manage a Web Server).
  3. Someone who can use and has access to an Image Manipulation tool.
  4. Someone who is comfortable coding and making edits to PHP, JavaScript and XML files.

Note: The creation and IP provisioning on our Windows Server was handled by two of my phenomenal colleagues. I did the rest of the server configuration, coding, and graphic asset development.  Please feel free comment on this discussion if you get stuck or have questions!  I will do my best to address any issues that come up.

Software Needs

  1. KennethWare 2.0 needs a Server! There are lots of options here:
    1. You can use a Hosted Server service or Internally Managed Server
    2. Picking the Server Operating System comes down to Windows Server, Linux, Mac OSX Server. From there it deciding the version or distribution.
    3. Configuring the Web Server.  You can pick IIS (Windows) or Apache (Can be used on any Server Operating System)
      1. The Web Server needs to have PHP enabled and MySQL installed and enabled. *While you’re at it, you may want to enable Python, since there are many Python Canvas scripts!
      2. The Web Server needs to have a IP Address (Example: and a Domain Address (Example: that are Public.
    4. HTTPS needs to be enabled and you will need a Digital Certificate.
      1. IIS and Apache can create a Self-Signed Certificate (free!) or you can buy one from a Certificate Authority Provider like
    5. PHP, MySQL, and cURL must be enabled on the web server


Important Note: I strongly advise you to NOT use a prepackaged “WAMP Stack”. WAMPServer, Bitnami, XAMPP, are excellent for Desktop Operating Systems like Windows 10 for creating a code testing environment.  They are not recommended for a “Production” Web Server. Proceed at your own risk with this route!

  1. A Code Editor. KennethWare 2.0 uses PHP and XML files.
    1. Adobe makes a really good, free(!) Code Editor called that works on Windows, Apple OSX. There’s a Linux version in development.
    2. TinyMCE is another great multi-OS tool!   
    3. Other choices include Adobe Dreamweaver, Sublime Text, Apple Xcode, Microsoft Visual Studio, etc.
    4. There are also many Browser extensions for Web Development and Coding for Chrome and Firefox users.
  2. An Image Manipulation tool.  There are JPEGs, GIFs, and PNGs that will need to be modified if you want to make the banner template
    1. Again, many options to pick from like Adobe Photoshop, Adobe Fireworks, GIMP, etc.

Server Setup

Most of our processes came from the article “How to manually install Apache, PHP and MySQL on Windows?” from If you opt for Linux or Mac OSX Server, these tools are very easy to install and configure.  We were more comfortable with Windows Servers based on our team’s experience.

Windows and Apache Setup

  1. We started with a Windows Server 2008 R2 that was assigned a Public IP address.

2.     We downloaded and extracted the Apache24 folder to the root of the hard drive with a path of C:\Apache24\.

3.     We opened a command line window (Windows+R and type cmdthen press Enter), change directory into C:\Apache24\binand run httpd.exe, normally it shouldn't print any errors.

4.     If you get an error dialog stating that MSVCR110.dllis missing on your system, you'll need to install the Visual C++ Redistributable for Visual Studio 2012 - as always, when prompted, select the appropriate bit-version : vcredist_x86.exefor 32-Bit systems and vcredist_x64.exefor 64-Bit ones.

5.     If you get an error saying that it can't bind to port 80, check if another application uses that port - also Skype is known to use ports 80 and 443 by default; uncheck "Use port 80 and 443 as alternatives for incoming connections" in its advanced connection settings, restart Skype to apply the changes, and then you should be able to start Apache without issues.

6.     A warning like Could not reliably determine the server's fully qualified domain namecan be ignored for now.

7. Windows Firewall may prompt you to allow Apache to communicate on specific networks, I recommend you use the default settings : allow it on home and work networks, but not on public/untrusted networks.

8.     Then, we opened a browser (Google Chrome) and browse to http://localhost, we saw a page saying It works ! which meant our Apache installation is working.

9.     Note: If you got a warning about not being able to determine the system's fully qualified domain name, fix it by editing C:\Apache24\conf\httpd.confand editing the ServerNamevariable (it should be already there in a comment, just uncomment it and change it) :

               Replace <yourhostname> with either the system's host name or localhost.

10. Finally, if you want to run the server automatically when the system starts (even if nobody logs in), you'll need to run it as a service - in a new elevated (as an administrator) command prompt, type :

11. That's it, now you have a new service in Services (Windows+R then type "services.msc" then press Enter) named "Apache2.4" that you can control just like any other Windows service.

a.   ServerName <yourhostname>
     httpd.exe -k install


  1. We downloaded the latest PHP binaries (PHP 7.0.3) from the official PHP for Windows download page. Choose the thread-safe version that matches your Apache installation's bit-version (x86 for 32-Bit, x64 for 64-Bit).
  2. We created an empty PHP folder at the root of the hard drive, and extracted the previously downloaded archive there. You should have a path like C:\PHP\

3.     In C:\PHP, we renamed the php.ini-production to php.ini.

4.     We opened that php.inifile, search for extension_dir = "ext"and uncommented that line (remove the first ;). This sets the default extension dir to ext(which resolves to C:\PHP\extand avoids having to prepend ext/to all extension's paths manually like in previous versions of this post.

5.     We then configured Apache to use that PHP, by editing C:\Apache24\conf\httpd.conf- after all the LoadModulelines, add the following :

6.     We started Apache manually by opening a command prompt in C:\Apache24\binand running httpd.exe- If you see no errors, it means your configuration file is valid and PHP is most likely working.

7.     You can test your PHP installation by creating a file like info.phpwith <?php phpinfo();inside and going to http://localhost/info.php- you should see quite a bit of info about your system and your PHP installation and all its modules. If you get something else like an "Internal server error" that means something's wrong.

8. You can now kill your current Apache process (Ctrl+C in the console) and start the service - the following part doesn't interact with Apache and can be done with the server already started.

9.     If you want to access your MySQL database from PHP, you'll need to enable extensions that allow you to do so, like php_mysqli or php_pdo_mysql - I recommend enabling them both.

10.  Open PHP's configuration file C:\PHP\php.ini in your text editor and search for php_mysqli or php_pdo_mysql - they should already be there, uncomment them.

11.  Done, now you can access any MySQL database using either mysqli or PDO.

LoadModule php5_module C:/PHP/php5apache2_4.dll
<IfModule php5_module>
    DirectoryIndex index.html index.php
    AddHandler application/x-httpd-php .php
    PHPIniDir "C:/PHP"


1.     On the MySQL Installer download page download the web installer mysql-installer-web-community-xxxxx.msi.

2. We used MySQL Community Server 5.7.12 - it was the latest version when this answer was last updated (look at the edit date at the bottom of the post).

3.     The installer will automatically install the appropriate version (32-Bit or 64-Bit) depending on your system, even though MySQL's bit version doesn't have to match Apache's and PHP's one but it's still beneficial to use the 64-bit version of your system supports it to take advantage of more than 3 GB of RAM, that's quite important as database servers tend to use a lot of RAM.

4.     We followed the steps in the installer, if you're installing this for development then the Developer defaultwill be your best option, it'll also install MySQL Workbench which is a native GUI client, thus avoiding you having to install slow web-based tools such as PHPMyAdmin if you aren't comfortable with using the command line client.

5. Once everything is installed the installer will ask you for some basic configuration values, I recommend disabling "Open firewall port for network access" unless you want to access the database from another machine on the network.

6. We set the root password - if it's only for development purposes and your firewall blocks incoming connections from the network then a strong password isn't necessary.

7.     Finally, you can disable the useless MySQL Notifier by right-clicking the tray icon, going into Actions -> Options, then untick the Run at Windows Startupcheckbox and apply. That'll save you a few MBs of RAM and avoid slowing your machine down when it's booting.

8. And that's it, you now have a fully functional WAMP server that runs as a service and doesn't depend on any user (accessible even if no one is logged in).

Setting up HTTPS on a Windows Server:

1.     We created a self-signed SSL Certificate using OpenSSL

2.     We then opened the command prompt and cd to your Apache installations "bin" directory. Usually it would be:

cd "C:\Apache24\bin"

3.     We created the SSL certificate we will need the openssl.cnf files location but the default location set by OpenSSL for this file is setup according to a Linux distribution, so we needed to fix it for Windows.

4.     We setup the Windows environment variable OPENSSL_CONF to point to the openssl.cnf files location. It is usually located in "C:\ Apache24\conf\openssl.cnf" directory.

5.     So we can set it up by the following command or through the GUI interface:

6.     set OPENSSL_CONF=C:\ Apache24\conf\openssl.cnf

7.     All files generated from the following commands will reside in "C:\ Apache24\bin" folder.

8.     Now that we had the environment variable set we need to create a new OpenSSL certificate request using the following command:

openssl req -new -out server.csr

9.     It will ask you some questions and you can safely ignore them and just answer the following questions:
PEM pass phrase: Password associated with the private key you’re generating (anything of your choice). 
Common Name: The fully-qualified domain name associated with this certificate (i.e.

10.  Now we need to remove the passphrase from the private key. The file "server.key" created from the following command should be only readable by the apache server and the administrator. You should also delete the .rnd file because it contains the entropy information for creating the key and could be used for cryptographic attacks against your private key.

openssl rsa -in privkey.pem -out server.key

11.  We needed to set up an expiration date. This could be any time of your choice, we used a limit of 365 days below:

openssl x509 -in server.csr -out server.cert -req -signkey server.key -days 365

12.  We then had a Self-signed SSL certificates ready to go. We need to MOVE the "server.cert" and "server.key" file to the

C:\ Apache24\conf" location.


Configuring Apache to run SSL/HTTPS server:

1.     Now that we had the Self-signed SSL certificate ready, all we needed was to configure Apache to start the SSL server.

2.     First we modify the "C:\ Apache24\conf\httpd.conf" file.

3.     We opened up conf\httpd.conf in a text editor and looked for the line:

4.     LoadModule ssl_module modules/ and remove any pound sign (#) characters preceding it.

5.     We included conf/extra/httpd-ssl.conf and removed any pound sign (#) characters preceding it.

6.     We modied the "C:\ Apache24\conf\extra\httpd-ssl.conf". We let all the default options as is but make sure to modify the following section according to your need:

<VirtualHost _default_:443>
DocumentRoot "Your Root folder location"
ErrorLog "logs/anyFile-error.log"
CustomLog "logs/anyFile-access.log" common
SSLEngine on

SSLCertificateFile "C:/Apache24/conf/server.cert"

SSLCertificateKeyFile "C:/Apache24/conf/server.key"

7.     Make sure that "SSLCertificateFile" and "SSLCertificateKeyFile" are properly located.

8.     For better organizing you can also put the whole <VirtualHost></VirtualHost> section in the "C:\ Apache24\conf\extra\httpd-vhosts.conf" along with your other Virtual Host settings there but you need to uncomment “Include conf/extra/httpd-vhosts.conf” in your conf\httpd.conf file to use that.

Opening SSL/HTTPS port on Windows:

1.     Now we need to open an exception in Windows Firewall for TCP port 443. You can do that by going to “Windows Firewall” settings in Control Panel and adding a port in the exception section.

2.     We restarted the server and everything worked!

Getting PHP CURL to Call HTTPS URLs on Windows:

We ran into a snag with using PHP CURL, but the Community helped us out! Here’s what we did to fix the issue.

1.     We downloaded the root CA certificates from a known good source. The most common is: (If you don’t want to download it this way and instead want to build it yourself you can use the perl script on that page or the VBS script here:

2.     We copied this file to the location c:\apache24\conf\cacert.pem

3.     If you’re running PHP version 5.3.7 or later you can edit your PHP.INI file to include: curl.cainfo = “C:/apache24/conf/cacert.pem”  Where PATH_TO is your actual path (c:/windows for example)

4.     That’s it problem fixed.  If you’re not running 5.3.7 or don’t have access to the PHP.INI file then you’ll add these two lines to your php script where you set your CURL options in the script:

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt ($ch, CURLOPT_CAINFO, “pathto/cacert.pem”);

KennethWare Setup

You will need to download the KennethWare 2.0 files from GitHub (

Note: It is highly recommended that you initially setup KennethWare in the Beta or Test instance of Canvas!

Where to start off was our “chicken vs. the egg” conundrum.  We started with the Canvas instance setup.

1.     We created an API token.  Anyone can create the API token, but we recommend that you have one of your Canvas Admin’s create it.

2.     We went to and generated the API Token.  We labeled our Purpose: Canvas Tools and did not set an expiration date.

3.     We copied the code to safe place:


4.     We created Developer Keys. and used the following settings on Developer Key

Key Name: Canvas Tools

Owner Email:

Tool ID: canvastools

Redirect URI:

Icon URL:


(You can leave Icon URL blank or use if you want to use a gray Canvas Logo.)


5. We took Developer Keys ID and Key and copied it to a safe place that could copied and pasted later.  The ID and Key values are going to be copied into the config.php into

$client_id =  and $clientSecret = fields.

6.     We added the code from canvasGlobal.js and canvasGlobal.css to our global Javascript and CSS files on our Canvas instance.

7.     We saved a copy the config-example.php to config.php and modified the following code:


      // Display any php errors (for development purposes)


      ini_set('display_errors', '1');





      // The URL for where the "wizard" folder is located


      $_SESSION['template_wizard_url'] = '';

      require_once __DIR__.'/wizard/resources/blti.php';

      require_once __DIR__.'/wizard/resources/cryptastic.php';

      require_once __DIR__.'/wizard/resources/meekrodb2.2.class.php';


      // Database connection information for Template Wizard

      DB::$host ='localhost';

DB::$port = '3306';

      DB::$user = 'root';

      DB::$password = 'OurDBPass';

      DB::$dbName = 'templatewizard';


      // Strings to help encrypt/decrypt user OAuth tokens

      $pass = 'xyz123';

      $salt = '123xyz';


      // Your Canvas OAuth2 Developer information. Used for getting OAuth tokens from users

      $client_id = '#############';

      $clientSecret = 'anotherrandomlistoflettersandnumbers';


      // The Shared Secret you use when setting up the Template Wizard LTI tool

      $lti_secret = "canvastools2016";

//You will need to use this field if you add KennethWare as an LTI.


      // Message to display if the OAuth token request fails

      $oauth_error_message = 'There is a problem, contact someone to fix it';


      // TEMPLATE ARRAY (templateName, minWidth,minHeight, ratioX,ratioY)

      // This array is for customizing banner images for template themes

      $templates = array (

            array('kl_fp_horizontal_nav_2', 1050,312, 215,64),

            array('kl_fp_panel_nav_2', 1050,312,  215,64),

            array('kl_fp_squares_1x1', 320,320,  1,1),

            array('kl_fp_circles_1x1', 320,320,  1,1)


      // RATIO ARRAY (ratioX, ratioY)

      $ratios = array (

            array (1,1),









      /* TOOLS API CONFIG  */



      // These variables for the Content Tools to make API calls

      $canvasDomain = '';

      // This OAuth token needs to make GET API calls for any course in your institution

      $apiToken = "1345~ thisisjustasamplestringtoshowthereallylongapicode ";


8.     We imported the tokens.sql file to our MySQL Database called Canvas_Tools

9.     We went to the folder and file js\tools-variables-example.js and saved as a new file called tools-variables.js

10.  We navigated to the images and wizard\resources\images and used Photoshop to modify the USU-related images to fit our school’s branding. We did this same for all banners and template_thumbs.

11.We uploaded our KennethWare folder to our Windows Server C:\apache24\htdocs\canvastools\

12.  We opened the folder and file wizard\ltiCode-example-enabled.xml and modified the following settings:

<?xml version="1.0" encoding="UTF-8"?>

<cartridge_basiclti_link xmlns=""

xmlns:blti = ""

xmlns:lticm =""

xmlns:lticp =""

xmlns:xsi = ""

xsi:schemaLocation = "">

<blti:title>Canvas Tools</blti:title>

<blti:description>Canvas course design and templating tools to help customize look of a course</blti:description>



<blti:extensions platform="">

<lticm:property name="tool_id">course_design_tools_1</lticm:property>

<lticm:property name="privacy_level">public</lticm:property>

<lticm:property name="domain"></lticm:property>

<lticm:options name="course_navigation">

<lticm:property name="url">https://</lticm:property>

<lticm:property name="text">Canvas Tools</lticm:property>

<lticm:property name="visibility">admins</lticm:property>

        <lticm:property name="default">enabled</lticm:property>

<lticm:property name="enabled">true</lticm:property>



<cartridge_bundle identifierref="BLTI001_Bundle"/>

<cartridge_icon identifierref="BLTI001_Icon"/>


13.  We went to the Settings/Apps tab and clicked “View App Configurations” and then “Add App”

14.  We went set the Configuration Type to “Paste XML” and used the settings

Name: Canvas Tools

Consumer Key: canvastools 

Shared Secret: canvastools2016

XML Configuration: copied all text inside the ltiCode-example-enabled.xml file to the field


Click Submit.


KennethWare is Now Ready to Test

1.     We opened a Demo Course on our Canvas instance and clicked on the external tool link “Canvas Tools”. 

2.     You will need to Authorize the LTI. 

3.     You will see a large chunk of text that will include lines like “OAuth2 Response Code:” and “OAuth token response:”, etc. This is normal!

4.     Click the link Proceed to tool index page or Refresh your browser page.

5.     Hurray!!!


You are now officially a KennethWare campus!  Rejoice as your faculty, administration, and course designers are heralding your mere footsteps!!!

Many thanks go out to the Community for posting so many excellent questions and responses about setting up KennethWare!   Special thanks to Kenneth Larsen,@Tatiana Peisl, & @Elena Northrup for contributing numerous invaluable threads on KennethWare.

I've written a user script that will add the Login ID and SIS User ID (if you're using them) to the User Search from the Admin page in Canvas.


Quick Install

For those power users who are impatient, here are the quick install steps.

  1. Install a browser add-on: Greasemonkey for Firefox or Tampermonkey for Chrome/Safari
  2. Install the Admin User Search Details user script.

When you are searching for a User from the Account page, it will automatically display the extra information.

It has been tested with Firefox, Chrome, and Safari.



I had a discussion with my Canvas Admin a few weeks ago about the Admin User Search. I was working on something, did a user search, noticed there was a duplicate name entry with no way to tell them apart and wondered what information would be useful. I was aware that the search functionality for users has long been a sore spot Advanced Admin Search & Sort , but I don't use it on a regular basis, so I hadn't devoted much time to it.


I have recently made some advancements in my JavaScript knowledge and was ready to make an attempt to do something about this. I whipped something up one night, coming up with different ways that it could be enhanced. I showed Kona Jones the working model the next day and asked her what she thought. She initially said it was wonderful, then before I ease the pain from patting myself on the back, she came back with a laundry list of things that it should do.


I looked into her list, which included the ability to filter users by term and decided that with the current API, there was little that I could do to speed up the process short of writing code that would query our local copy of the SIS database instead of the one maintained by Canvas'. While most of that information is available locally, there's something nice to be said about having it directly available within Canvas and part of the user interface. Besides, I already have a lookup tool that our local admins could use to find a student SIS ID and then search by that to get the results quickly within Canvas.


The bottleneck is the Canvas search. At our institution, with only about 13,500 users, when you search for "Jones" or "Smith", you get about a 25 second delay while Canvas searches for that information and returns a paginated list of 118 users (Jones) or 169 users (Smith). Subsequent reloads within a short time or moves to the next or previous pages are much faster. But it's that initial delay that is the killer and there's nothing I can do to speed that part up.


So, deciding I wouldn't be able to help Kona with her dream implementation, I focused on what was available.


Sometimes, Canvas returns information on the page but just hides it from the user. I held out hope, because the API call to search for users returns lots of information like the full name, sortable name, SIS user ID, and login ID. In some lists of users, you can get the email address, the enrollments, and the last login. Unfortunately, no matter what was being fetched to generate the page, the only thing being stored on the page was the name of the user and the URL to the user's page.


Considering some of the incredible markup and nested divs that Canvas uses in a lot of places like the modules page, it was actually very boring markup: a simple unordered list that was returned as part of the page itself, rather than an AJAX call as becoming more frequent for loading information.


After the 9+ To Do fiasco of February 20, I had written Restoring the Needs Graded count  (by the way, if you installed that script, you should disable it) and now knew how to fetch information about each item on a page. So, I took what I had learned there and fetched the user information for all 30 users that was listed on the page. I then appended the Login ID and SIS User ID to the user's name and I formatted it to look more like a table than a list.


Kona influenced the design, so if you don't like it ... Anyway, I had three ideas for displaying it. 1) look for duplicate names and only fetch the information for those names, 2) wait until a user mouses over a name and then fetch it, displaying the information as a tool-tip if they hovered over the name, and 3) load the information for all users on the page, possibly with a delay of a few seconds in case the name was easily located.


Kona said she wanted the information for all of the users, even if there wasn't a duplicate name, she didn't like the tool-tip, it was extra work on her part, and she wanted the information immediately. So that gives us what I'm announcing today.


Canvas is Doing Something

Kona told me that Canvas was working on something and that it would hopefully be coming soon. Renee Carney wrote on March 7, 2016, that it is currently in code review and that hopefully it would be appearing in one of the next few releases. It didn't show up in the March 12 release and after code review, it has to go through Beta before making it into Production, so it's at least a few weeks off. I asked Kona whether I should go ahead and release this or just wait for Canvas to do something. She said to go ahead and release it.


As with much of what I write, I hope that it is temporary and that Canvas will do something much better and this can be retired. As mentioned earlier, they are the only ones that can speed up the search.


Why Not List the Courses?

When developing this, I thought about adding currently enrolled courses to the list. The enrollments API will filter enrollments by state, but we don't conclude our courses at the end of the term and so the "active" courses included all of the previous ones as well. Then the names of the courses weren't included in the enrollments, just the Canvas and SIS IDs for them. You can get a list of courses for a user (if you have admin privileges, which shouldn't be a problem here, but it might be specific to masquerade permissions), but that might not return the dates of the course if your school puts them on the section instead and it doesn't include the user information. For the same reason, the email addresses were an additional API call when it wasn't already their Login ID. Basically, adding anything extra boiled down to a lot more complexity and time (network API calls) involved to get all of that information and I wanted something that would be reasonably quick. Canvas displays just 30 names at a time, so it makes 30 calls to the API to fetch the user information and it's pretty quick about it -- although you'll be able to see it update the screen as it fetches the information.


Stop Babbling and Show Me!

Fair enough.

I did a search for Michael Smith since he is our most popular name (having a local copy of the database made that easy to find).


Native Search Results

This is what it currently looks like:

Enhanced Search Results

After installing the user script, you get this:


Note: Your screen won't actually contain the blur, that's done for FERPA reasons.



The script should run as-is on any site that doesn't use a custom domain name. If your Canvas instance doesn't end in, then you'll need to edit the \\ @include on line 5.


The source code contains a configuration variable with a columns array inside of it. This contains the information to display, the order to display it in, and any extra CSS classes you would like to apply to that column.


Currently, it displays the login_id first and then the sis_user_id. Our sis_user_id values are numeric, so I applied the text-right class to that column so they are right-aligned. If you have alphanumeric SIS codes, then you could take out the class value (and the comma on the line before it).


Other values besides login_id and sis_user_id that you might use include:

  • id: The Canvas User ID. You can get this now by mousing over the URL
  • sis_login_id: We use the same thing for our Canvas Login ID, so I didn't include it, but others might have them be separate values
  • avatar_url: If you wanted to display the location of their Avatar, you could include this. You probably don't want the location, though, you would want the actual avatar to show up. That's extra functionality that would have to be programmed into the system.
  • permissions: This is a really incomplete list of what the user can do. For example, my user record has can_update_name: false and can_update_avatar: true.

There are different variations of the name. name, sortable_name, and short_name.



This script is a Canvancement and designed to improve the user's experience with Canvas. It is up to the user to decide whether or not to use it. The source code is available on the Canvancement website.


When Canvas releases their improved user search, you will probably want to disable this one. In the meantime, I hope someone can benefit from it.














because we all get to go to camp anyway.


See you in July!

At Eastern Washington University we've built an LTI called Threadz that is open sourse and available for anyone to install at their own institution.  Threadz is a discussion visualization tool that adds graphs and statistics to Canvas discussions.


Online discussions provide valuable information about the dynamics of a course and its constituents. Much of this information is found within the content of the posts, but other elements are hidden within the social network connection and interactions between students and between students and instructors. Threadz is a tool that extracts this hidden information and puts it on display.


The visual representations created from social network connections and interactions between students and instructors in a discussion assist in identifying specific behaviors and characteristics within the course, such as: learner isolation, non-integrated groups, instructor-centric discussions, and key integration (power) users and groups. By identifying these behaviors and characteristics, the instructor can affect change in these interactions to help make the discussions and classroom discourse more accessible to all.

More information can be found on the Threadz website.


The files to the LTI can be found on github at: mcjelewis/threadz · GitHub




funny-trivia-questions.jpgUpdated: March 1, 2019

Clarified the formatting of "Matching" question types.


If you currently create quizzes in Canvas manually (question by question), there is a quicker solution: Respondus 4.0: Exam Authoring Tool.  (This is a paid product, so you'd need to check with the appropriate people at your school to see if purchasing is an option.  At our Technical College, we only have a few licensed copies for people in our department.)  The Respondus software allows you to batch-upload multiple quiz/test/exam questions contained in a single file to the software.  Those questions are then uploaded into a Canvas course.  For those of you who already have Respondus or for those of you who are thinking of purchasing...this blog will attempt to give you examples of how to properly format files that Respondus can "read".


When we get quiz/test/exam questions from our faculty to put into Canvas, I prefer to create these questions in either Microsoft Notepad or WordPad.  If the questions don't have any special text formatting, then Notepad works great!  I save these files as *.txt files.  However, if questions have simple formatting that needs to be included (bold, italics, underlining, subscript, superscript, etc.), then WordPad can tackle that for you.  I save these files as *.rtf files.


Before creating the files, though, you need to make sure that you have a few basic things:

  • Questions
  • Answer Key
  • Number of points per question


Now that you have these things, you can begin creating your file(s).

Even though Canvas Quizzes have multiple types of questions you can create, the question types that Respondus recognizes is more limited.


There are two different ways to format it's really your decision on which method you prefer.  In either case, you'll want to make sure that your formatting is consistent throughout the file. For example, there should be one line of space between the end of one question and the beginning of the next.

Example 1

All questions in this example use a period after the question numbers and possible answer choices (though you could also use a closed parentheses instead as shown in Example 2 below).  There should be a single space between the period and the start of the question or possible answer.  Correct answers are indicated with an asterisk.

For Question #1, instead of "True" and "False" as your answer choices, you could also use "T" and "F" (without the quotes).  Canvas will automatically detect it as a True/False question type even though the question Type is not specified.

1. Albert Michelson determined the exact speed of light?

*a. True

b. False

For Question #2, Canvas will automatically detect it as a Multiple Choice question type even though the question Type is not specified.

2. Who determined the exact speed of light?

a. Albert Einstein

*b. Albert Michelson

c. Thomas Edison

d. Guglielmo Marconi

For Question #3, Type: MA needs to be included before the start of the question to tell Respondus this is a Multiple Answer question...compared to question #2 which only has one correct answer.  You can also use MR (Multiple Response) as your Type.

Type: MA

3. How many of the given shapes consist of at least three angles? (Select all that apply.)

*a. triangle

*b. square

c. circle

*d. trapezoid

For Question #4, Type: F needs to be included before the start of the question to tell Respondus this is a Fill In the Blank question type.  The possible correct answers are listed below.

Type: F

4. Who is known as the "father of television"?

a. Zworykin

b. Vladimir Zworykin

c. Vladimir Kosma Zworykin

For Question #5, Type: MT needs to be included before the start of the question to tell Respondus this is a Matching question.


Also, it's been my experience that putting the definition first and then your term second is the better way to go.  Once loaded in Canvas, your students will have a drop-down list of terms to choose from rather than seeing a drop-down list of (potentially) long definitions.



a. A large bearlike mammal with characteristic black and white markings, native to certain mountain forests in China, and feeds almost entirely on bamboo. = Panda

Type: MT

5. Match the correct name to the discovery or theory.

a. Michelson-Morely = Speed of light

b. Einstein = Theory of Relativity

c. Marconi = radio waves

For Question #6, Type: E needs to be included before the start of the question to tell Respondus this is an Essay question.  There isn't a "correct" answer with this question type.

Type: E

6. How is the Michelson-Morely experiment related to Albert Einstein's theory of relativity?


Example 2

All questions in this example use a closed parentheses after the question numbers and answer choices (though you could also use a period instead as shown in Example 1 above)There should be a single space between the closed parentheses and the start of the question or possible answer.  Correct answers are NOT indicated alongside the questions.  They will appear at the end of the file.


Refer to Example 1 (above) if you have questions about the Type lines.

1) Albert Michelson determined the exact speed of light?

a) True

b) False


2) Who determined the exact speed of light?

a) Albert Einstein

b) Albert Michelson

c) Thomas Edison

d) Guglielmo Marconi


Type: MA

3) How many of the given shapes consist of at least three angles? (Select all that apply.)

a) triangle

b) square

c) circle

d) trapezoid


Type: F

4) Who is known as the "father of television"?


Type: MT

5) Match the correct name to the discovery or theory.

a) Michelson-Morely = Speed of light

b) Einstein = Theory of Relativity

c) Marconi = radio waves


Type: E

6) How is the Michelson-Morely experiment related to Albert Einsteins theory of relativity?


At the end of the file, Answers: indicates the start of the answer key for the quiz/test/exam.


  • For question #1, you can also specify the "correct" answer as "T" for "True" or "F" for "False"...or use the actual words "True" or "False" (without the quotes).
  • For question #3, you can also enter the correct answers as: "A,B,D" or "A B D" (without the quotes).
  • For question #4, each possible "correct" answer is listed separately.


1. A

2. B

3. A, B, D

4. Zworykin

4. Vladimir Zworykin

4. Vladimir Kosma Zworykin




Finally, there is a way to include feedback for your questions which shows up after the quiz/test/exam has been taken.


Example 1

General feedback can be imported by placing the tilde ~ symbol in front of the feedback for a correct answer (see green "Correct answer comments" box below).  The @ symbol can be used to indicate the feedback for incorrect answers (see red "Wrong answer comments" box below).  There must be one space between the @ or ~ symbol and the start of your feedback.  A blue "General answer comments" box is also included in the Canvas interface, but I haven't found a way to include that in my text files at this time.  So, I manually typed in that feedback after I uploaded the questions to Canvas.  


General Feedback


You can also combine this method of feedback with the method described in Example 2 below.


3) Who determined the exact speed of light?

~ Yes. Albert Michelson won the Nobel Prize for Physics for determining the exact speed of light.

@ No. The correct answer is Albert Michelson, who won the 1907 Nobel Prize for Physics for determining the exact speed of light.

a. Albert Einstein

*b) Albert Michelson

c) Thomas Edison

d. Guglielmo Marconi




Example 2

To import feedback for individual answer choices, place the feedback immediately after the answer choice and begin the line with the @ symbol.  There must be one space between the @ symbol and the start of your feedback.


You can also combine this method of feedback with the method described in Example 1 above.

3) Who determined the exact speed of light?

a. Albert Einstein

@ No. Albert Michelson determined the exact speed of light.

*b) Albert Michelson

@ Yes. Albert Michelson won the Nobel Prize for Physics for determining the exact speed of light.

c) Thomas Edison

@ No, Thomas Edison did not determine the exact speed of light.

d. Guglielmo Marconi

@ No. Marconi did not discover the exact speed of light, but he did win the Nobel Prize for Physics for his work with radio waves.


These are the basic question types that I have used the most.  If you know of other types that also work in the Respondus software, feel free to comment. 




In part of this discussion thread, Is it possible to import quiz questions with feedback for each response using Respondus?, Tara Bunag and Elizabeth (Online Learning) Jackson discuss adding images to quizzes via MS Word documents.  I won't repeat the information they've already shared here in this blog, but I will share how this can be accomplished using either Notepad (*.txt files) or Microsoft Wordpad (*.rtf files).


To start, make sure that any images you use are JPG, JPEG, or GIF formats.  These images should be stored in a folder you create on your computer.  For the below example, I will included an image of Kermit the Frog in the question.  The image name is Kermit.jpg.  Now we can begin to create our questions in Notepad or Microsoft Wordpad.  Here's an example question with several areas of feedback for students once the quiz has been taken:

  • Highlighting is my own.
  • The first line with the Title is optional.
  • The second "Kermit" (shown in blue) in the question is supposed to be for the ALT text for the image, but in my own testing, this hasn't transferred over from Respondus to Canvas.

Title: Muppets
1) Which Muppet is pictured here? [img: "Kermit.jpg" "Kermit"]
~ Yes, this is Kermit.
@ No, this is not Kermit. Kermit is green in color. You picked a Muppet who isn't green.
a. Gonzo
@ This is not Kermit. This is his weirdo friend, Gonzo.
*b. Fozzie
@ This isn't Kermit. This is his bear friend, Fozzie.
c. Kermit
@ Yes, this is Kermit the Frog.
d. Miss Piggy
@ No. This is Miss Piggy.

Make sure that you specify both the File name location of your quiz file AND the Image Folder location...otherwise Respondus will not upload the file for you.



Once you have uploaded your quiz to Canvas via Respondus, you'll probably be curious as to where your image got stored in your course.  Head on over to your course Files area.  Find and open up a new folder in there called Quiz Files.

The Quiz Files folder (and all sub-folders within it) folder is set to "Hidden. Available with a link."

Next, open up the qti_import_NNNNN folder where NNNNN is a five digit number.  Your image(s) should be in this folder.


As a final note, you may want to check over your quiz that you just uploaded to Canvas to make sure any images you included are positioned correctly within the questions.


Here's the final result:


Student Perspective

Muppets Quiz 1

Instructor Perspective

Muppet Quiz Choices

Filter Blog

By date: By tag: