Our college purchased a course evaluation tool (Class Climate from Scantron) with a very limited Canvas integration. This integration requires that link be placed in every classroom as an "External Tool" content item in a module. As a two-person office, adding this to 900 courses manually presents a bit of a challenge.
Our thought was to create a module template with this link, then push it out to all courses each quarter. We have no idea if this is possible, and if it is possible we have no idea how to do this.
Does anybody have any ideas, or past experience with a Class Climate integration where they accomplished this?
We could sure use the help.
Thanks in advance,
Kelley
@kmeeusen ,
Oops - I originally misread External Tool as External URL.I updated the original instructions. Sorry about that.
Yes, it can be done using the API.
With External Tools, you will need to configure it on the Account Level first before doing this process. You could alternatively put it into each course if the configuration needs to be different for each course. You will need the id of the External Tool for step 3 of the process. You can obtain that through the External Tools API or by adding it to one course and then getting the content_id from List Module Items method in the Module API.
Example: Use the List External Tools method from the External Tools
GET /api/v1/accounts/:account_id/external_tools
You may want to add ?per_page=100 to the end if you have more than 10 external tools and the one you want doesn't show up.
It returns a list of external tools. Find the one that you want and make a note of the id. That will be used in step 3 for the content_id.
Big NOTE! This assumes that you are not actually returning a grade back into the course. If you are, then you need to create an assignment and use the content_id of the assignment rather than the content_id of the external tool. According to the ModuleItem Object documentation, the content_id is the id of the object referred to applies to 'File', 'Discussion', 'Assignment', 'Quiz', 'ExternalTool' types
Once you have that prerequisite information, you can do the following:
The flow is like this:
Step 1: You may already have a list of courses somewhere, if not, you can use the List active courses in an account method from the Accounts API. Specify the enrollment_term_id (using the Canvas ID, not the SIS ID, for the term).
Step 2: Use the Create a module method from the Modules API
POST /api/v1/courses/:course_id/modules
The only required information is the module[name]. You'll want the name to be unique across all the courses and identifiable to the students.
This POST should return a Module object, which will contain an id field. That is the :module_id needed for the next step.
Step 3: Use the Create a module item method from the Modules API
POST /api/v1/courses/:course_id/modules/:module_id/items
You'll want to specify:
This POST should return a ModuleItem object that will contain an id field that may be needed for the publishing
Step 4: Publish things ???
The create module and create module_item methods don't document a publish feature. That suggests that creating the module and publishing it are two different things. If it turns out that they come out published by default (I haven't tested), then you can skip this step completely.
Test the first three steps for a single course in our test site and see whether or not they come out published. If they don't, then you'll need one or two extra steps.
Step 4a: Use the Update a Module method from the Modules API to publish the module.
PUT /api/v1/courses/:course_id/modules/:id
The :id is the module id found in step 2.
The only thing you should need to put is module[published]=true
Step 4b: Use the Update a Module Item method from the Modules API to publish the External Tool in the module.
If the Publishing of the module automatically updates publishing of everything in it, this step will be unnecessary. But I haven't tested it, so I don't know.
PUT /api/v1/courses/:course_id/modules/:module_id/items/:id
The :course_id is from step 1, the :module_id is from step 2, and the :id is from step 3.
The only thing you should need to put is module[published]=true
Repeat steps 2-4 for each course obtained in step 1.
As with any POST, PUT, or DELETE command, test the whole thing in your test instance first. I generally use the live site if all I'm doing is a GET.
@James
Thanks you, thank you, thank you!
If we pull this off, it will be our first API call. We will try this soonest!
Kelley
Do you have a programmer in your midst? You can walk though a one-time deal by hand but to do that many courses, you'll really want to do a script of some kind. APIs can be intimidating for the first time user, but they unleash a lot of power behind Canvas.
I was telling Kona last night that problems like yours are things that I would love to solve and it would probably be faster than explaining how to do it. With the libraries I've written, I could probably have it done in 20 minutes or so. Unfortunately, my libraries are heavily customized for our setup and not generally usable by others. On top of that, my online course we talked about at the Unconference has been consuming most of my time (only 3 days left). I was thinking that if I could get that Google Spreadsheet written that Dayton wanted for the evil grade distribution that would really make it easier to share solutions with people - I could just share a spreadsheet and then people wouldn't need to know API. Of course, Javascript isn't one of my primary programming languages so that's slow going too.
All that is a long way of saying that if you need help, just ask.
James:
We have reached out to one of our programming instructors - we know when we are in over our heads.
Really appreciate your help.
You and Kona are real kindred spirits!
By the way, Kona.
I am still very very far - as in a Galaxy far far away - from the heady heights of Level 5, but I did just now make 10th place in the rankings.
Out of 10,000 users, that ain't too bad!
Wow @kmeeusen ! I'd say that is pretty awesome and quite an achievement! Congratulations!!
I came here trying to understand content_id, and i hate to say, it still is not very clear.
My use-case for which i am trying to use this field is that I am building an LTI tool which will render external content in course modules. To render that content, I need to store an ID of the content to show in specific modules. i was hoping i can use this field for this purpose.
But i tried doing it, it saves the content_id(I am creating course modules and module items through APIs), but doesn't seem to use it or send it with LTI launch or anything.
Any help in this regard will be great. Thanks.
... doesn't seem to use it or send it with LTI launch or anything.
Most LTIs don't need internal Canvas IDs to operate. They have their own IDs and use the opaque identifiers that Canvas may send.
However, there are some variable substitutions that are allowed and one of these is Canvas.module.id.
When you set up your app, add something like this (the left side can be whatever) to your custom fields.
module.id=$Canvas.module.id
Then, you'll get a field in the LTI launch data for custom_module_id that contains the id of the module.
If you need the moduleItem, then use $Canvas.moduleItem.id
Thankyou for the swift response James, only issue is that i dont need canvas generated ids of modules, i need some custom data i want to store as kind of meta data in the moduleItem.
Anyway, i figured this can be done using the GET params in LTI launch URL, as discussed here Query parameters included in request body for LTI launch requests · Issue #600 · instructure/canvas-... so my issue is resolved.
But to me, the content_id's use is still not clear.
@kmeeusen , I would recommend you checking out the (if you didn't attend it in person) as it sounds like exactly what you're looking for.
That looks like it would have been an interesting one to see, sorry I missed it.
I did notice they gave wrong information in the 15-16 minute mark about using SIS codes. There is a set of parameters that can be replaced by SIS codes. They mentioned writing an app that would convert SIS codes into Canvas codes, but that functionality is built into Canvas already and for many things, you don't need to.
They mentioned you can do lots of things, but didn't have the examples of doing multi-step processes. It seemed like what they were doing was calling the same API over and over. I didn't see, and don't use Postman to know, if it allowed the multiple steps that Kelley needed of using the information from one API call to make the next API call.
Still, a good presentation.
Thanks for the input @James . I'm obviously displaying my "non-coder" abilities (or lack thereof) by wholesale suggesting the session which I look forward to implementing and hopefully saving me a day or two worth of work.
It does sound pretty cool and I hope you do save those two days of work. For repetitive single-API calls for non-coders it looked really promising. Maybe a session next year can be a follow-up on accomplishing mutli-stage tasks.
If it's geared toward non-coders, I will be there. :smileygrin:
I must agree with Mark!
It would be nice to see any API sessions that were geared towards non-coders.
Many of us who administer our LMSs on our campuses are non-coder. With most of the legacy LMSs we migrated from, no coding was necessary. Now that we are in Canvas, we know that we can greatly expand our effective use of Canvas if we can code, and are struggling to get at least a minimum of expertise.
The last API sessions I attended at InstCon were much too far above my tired old head.
I agree about the non-coder stuff! While I'm lucky to have James around to do the heavy lifting, there are a lot of times that I'd like to be able to do things on my own without having to ask for his help!
There are lots of times I wish the same thing @kona
But sometimes it really is better to let an expert do it because we are more familiar with the consequences of particular actions and their ramifications on other items. Asking someone who hasn't poured through the API documentation (coder or non-coder alike) to try something is always a questionable decision. As was mentioned in the video, you can do serious damage with the API. The GETs are pretty safe, but always test POST, PUT, or DELETE in a test or beta instance.
When I take really complicated things in the API and make them look easy, I like to joke that "I'm a professional driver on a closed course, and you should not try this at home." But, unlike some professions, I don't mind sharing with someone how to do something so they can empower themselves. II don't see my car mechanic telling me "here's how to adjust your timing belt -- go have fun."
hanks, Mark, and I will check it out. I note that @James noted a coding mistake part-way in, but I would not know the difference at this point in my coding journey.
Cripes! 64 years old, two jobs, raising a grandchild and now I am trying to learn coding. I do everything in reverse order some times:')
Just to follow up on this, I've now used the Postman process 3 times (without changing anything from their presentation) and it's worked wonderfully and really has saved me from having to manually import from a template to 150+ courses.
Mark, I just watched this and I am struggling with how this saves more time than just doing a course copy since I have to find and make a list of the course URL codes first anyway? If I have to open the course to get that, why not just go to the settings and do a copy? Someone save me!
macaulayl, I use the Provisioning Report that is available to account-level admins. Here's the Canvas guide where you can learn more about it: How do I view reports for an account?
I set the settings to be the term that I want, include deleted objects, and select only the "Courses CSV." The resultant CSV download provides me the "canvas_course_id" for all courses in a given term. I simply copy and paste that column from the CSV download into my Google Spreadsheet. Below is a screenshot of a portion of what my provisioning report looked like when I was setting up the Fall 2016 term. It takes all of 10 minutes to do this.