Google Apps Script: Upload grades into a Google Classroom Coursework Assignment

Grade Upload for Google Classroom

Google Classroom, Google Sheets, Google Apps Script: Classroom API, SpreadsheetApp, map, forEach

At the date of writing this the world is in the midst of a worldwide pandemic – the Corona Virus.

For educators and their Igors administrators like me, it has been an incredibly busy couple of months.

Many of us have quickly sort to use online resources and tools to keep in contact with our students and take a crash course into the world of online teaching.

Google Classroom has become one of the darlings of the teaching world that has come out of this crisis. Its shallow learning curve and attractive UI made it an obvious choice for most educators. Oh, and I am sure the fact that it is free helped too.

For all of Google Classroom’s ease of use, I still feel the application is in its fledgling stages and does have a few limitations that, I’m sure, Google is constantly working on and improving.

One of the limitations is that you cannot simply upload grades from, say Google Sheets or another assessment tool. Well…not directly in the Google Classroom platform, yet.

However, you can still upload grades from an external source using Google Apps Script. You could use GAS to upload a whole courses grades from a Google Sheet. You could even use GAS to upload grades on a trigger from another assessment’s API into your Google Classroom.

In this tutorial, I am going to run you through the basics of uploading grades into Google Classroom using Google Apps Script with the Classroom API.

NOTE! This tutorial is for a wide audience. Feel free to read the post all the way through, or take what you need and get cracking!

The Example: Dyson Sphere Construction 101

The best way to explain how to upload grades into Course Work in Google Classroom is with an example.

Behold! My example Google Classroom: Dyson Sphere Construction 101:

Google Classroom Dyson Sphere Construction 101 Stream

If you click on the Classwork tab you will see that we have separated our classwork into 3 units.

Google Classroom Dyson Sphere Construction 101 coursework

The units are created by selecting the Create button and selecting, Topic.

Imagine that we have used an external assessment tool that we have then downloaded the results from and put into a spreadsheet:

Google Sheets Grade Resuls to be uploaded to Google Classroom

Fortunately for us, the downloaded grades use our student’s emails. We can use these as a reference ID to the students in our Google Classroom.

The Setup

In Google Classroom, all the courses, students, teachers, coursework etc all use unique numerical reference numbers to locate this information. This means before we can run our upload, we need to find all these IDs.

Creating a new Google Apps Script Project

Navigate to your Google Apps Script main page and create a new project.

Give your project a title. Then rename the Code.gs file to Setup”.

Next, go to File > New > Script file and create a new *.gs file called, “Test”.

Set up the Classroom API

Google Classroom API is an advanced API. This means that you will need to add it to your project before it will run.

To do this, go to your GAS console and navigate to Resources > Advanced Google services.

Google Apps Script Console Advanced Google Services

You may get a warning to accept the Cloud Console Terms of Service. If so, click the link.

GAS warning to accept the cloud console TOS

Another browser tab will open in the Cloud Console. Accept the terms of service and click AGREE AND CONTINUE:

Google Cloud Platform TOS

Go back to your GAS console and try again (Resources > Advanced Google services):

Advanced Google Services API list in GAS console

Navigate to Google Classroom API and check the box on the right to on. Then hit, OK.

Noice! You are ready to start coding.

Find the Course and Owner

First, we need to find the ID of the course we want to add our grades into.

In your Setup.gs file type in the following code:

In your Test.gs file, add the following  run code:

This code will return a list of courses with the following details:

  1. The course name.
  2. The course id.
  3. The owner of the course.

From this information, we should be able to easily find the course we want to add our grades into.

Go to the Test.gs file and run the runGetCoursesID() function.

You will need to accept a bunch of permissions to run this code.

Once complete, the code will have logged all the courses that you have created*. Next, head over to the Stackdriver log to view the logged results (View > Stackdriver Logging). This will open a separate tab.

*If you are on your own GSuite domain (e.g. www.yagisanatode.com) and you have full administration privileges, then you may be able to see all the courses that all the users in your domain created. 

You should end up with something like this:

You can now see that our Dyson Sphere course has an id of: “83743632546”.

Your ID will, of course, be different.

Save the ID for your course. You will use this later.

Code Breakdown

runGetCoursesID()

The runGetCoursesID() function simply logs the results of the findCourseAndOwner() function.

findCourseAndOwner()

First, we want to get a list of all the courses. We do this with the Google Classroom API’s Courses reference.

If we use the list method we can then get a detailed object list of each course with a heap of details (Line 11). Part of this object will contain the course ID and its title.

Don’t forget to add the courses bit at the end to get to the array of courses.

Next, we will use Javascript’s map to iterate through each course and return only the course (Line 13):

  • ID
  • Title
  • Owner of the course

To find the owner of the course we need to dig into the Courses Teachers resource(Line 14).

We use the get method here. The Courses.Teachers.get method takes two arguments:

  • The course ID
  • The teacher ID

We draw our course ID from our list of courses as our map iterates through each course. We want the name of the owner which will be one of the teachers on the course. In our get method we reference the currently iterated course ID and the ID of the owner.This will give us a detailed set of key-value pairs about the teacher. We then select the profile key, it’s child, name, and that child key fullName. The name of this teacher will be the owner of the course.

Finally, we return a string containing our owner name, the course id and the course name.

The ownerName array of mapped items is then returned once the findCourseAndOwner() function is run.

Getting a list of students in your Google Classroom Course

While not a directly essential part of uploading grades to Google Classroom. You may need to use your list of student emails, and ids for your course to compare against the grades you are going to upload from your Google Sheet or via some other resource.

This code will provide you with a list of student’s:

  • ID
  • Email
  • Full name

To upload grades you will need to reference either the student’s ID or email address. The Full name is used as a visual reference so you know what students you are looking at.

In your Test.gs file paste the following code:

You will need to add your selected course ID you discovered from running the runGetCoursesID() function previously.

In your Setup.gs file add this code:

Running the getStudents() function from the Test.gs file will result in a list of student details like this:

Code Breakdown

getStudents()

In the Test.gs file getStudents() first requires the course ID we found earlier with findCourseAndOwner()(Line 2).

Then we run the getStudentDetails(courseID) from the Setup.gs file to return our student list of results. For us, we just logged the results (Line 4). However, you might want to directly input the student list into a Google Sheet or something.

getStudentDetails(COURSE_ID)

This function takes the course id parameter and returns a list of students from that course.

Our first step is to get our list of students using the Classroom API’s Course.Students.List method. This method takes one parameter, the courses ID. This will return a comprehensive list of details for each student on the course.

Next, we simply map through each of the students grabbing their ID, full names and emails:

Getting the Classroom Topic Items

We want to put our course assignment and the grades into a specific Topic, Unit 2, in the Classwork tab of the Google Classroom dashboard. To do this we will need to find the topic’s ID.

Google Classroom Topics Intesert

To get a list of topics and their corresponding IDs, add the following code to your Test.gs script.

Then, add this function to your Setup.gs file.

When you run getTopicList() from the Test.gs file, it should log the following results:

Now we know that our Unit 2  has the ID, 83743632579.

Note: I think, by now you probably have figured out what the Test functions do, so I will skip them in the code breakdown from now on. 

code Breakdown

getTopics(COURSE_ID)

The getTopics(COURSE_ID) function takes the course ID and returns an array of all the topics along with their assigned unique IDs.

To get a list of all the Topics and their details we use the – yep…you guessed it – the Courses.Topics.List method.

We then use JS map to iterate through each topic and store the ID and name of the topic.

Uploading the grades

Once we have run our setup we should have 3 important IDs:

  1. Course ID
  2. Topic ID
  3. Emails and ID for students (we will use the emails here to put on our Google Sheet)

One of the challenges of uploading grades to Google Classroom is that we can’t create an assignment in the Classroom dashboard and then upload grades directly to that assignment. Instead, we need to create the assignment programmatically. For us, we will do this in Google Apps Script.

More on this in a minute.

The Code:

In your Google Apps Script editor, create a new file and call it CourseGrades.gs. Paste in the following code:

Quick Use Guide

assignGradesToNewCourseWork() is your main run function to upload your grades into Google Classroom.

You will notice at the start of the function that there are 3 global variables:

  1. COURSE_ID
  2. TOPIC_ID
  3. COURSE_INFO

For the COURSE_ID and the TOPIC_ID, you will need to update the IDs based on the results of running the functions in the setup.

COURSE_INFO

The COURSE_INFO variable is an object containing all the information you will need to create a new coursework assignment. Essentially, anywhere where you see a // <<< UPDATE THIS, you will need to modify for your project.

Let’s take a look at what is in this object:

  • "assigneeMode": "ALL_STUDENTS" – Keep this. This will assign the assignment to all students in your course.
  • "associatedWithDeveloper": true – Keep this. This is a must-have item that tells your classroom that this assignment was built programmatically and can, then be updated programmatically.
  • "description": "" – Update this. You will need to put your description of the assignment here. You can also leave it blank.
  • "maxPoints": 40 – Update this. Assign the maximum points for this assessment.
  • "state": "PUBLISHED" – Keep this. You will probably want to publish this assignment right away for your students.
  • "submissionModificationMode": "SUBMISSION_MODIFICATION_MODE_UNSPECIFIED" – Keep this. This sets the assignment so that the assignment is never returned. Basically, student are not going to submit anything – they are just going to see their grades.
  • "title": "" – Update this. This is the title for your assignment.
  • "workType": "ASSIGNMENT" – You can make this an assignment or COURSE_WORK_TYPE_UNSPECIFIED the grades will be retained the same way.
  • "topicId":TOPIC_ID – This is the id of the topic we want to add our assignment to.

GRADES

On line 34, we collect the grades to be uploaded into your Google Classroom coursework. The file should return an 2d array containing either a student ID or their email and a grade.

For our example, we are calling a Google sheet with a list of grades. I’d imagine that this would be a fairly common use case unless you are directly connecting to an assessment API.

The GRADES variable runs our importGrades_()  function that grabs our grades.

const GRADES = importGrades_()

If you are also importing grades from a Google Sheet, you can navigate to line 56.

Here is what you will have to update:

  • ss – Change the ID to your own sheet id. You can find this in your browser when you are in your Google Sheet.
  • sheet – select the sheet tab name that your data is on.
  • range – This is currently set for a sheet containing two columns with a header starting in row 1.

If you want to find out more about working in sheets, you can check this post out: 

Can I modify Google Sheets with code?

Run The Code

After setting up your global variables in the assignGradesToNewCourseWork() function and preparing your function to grab your grades for import. You can run the assignGradesToNewCourseWork()function.

Once the code is has completed its run, you can return to your Classroom Coursework page and see that the new coursework item had been created and the grades have been added.

For our example, it will look like this.

Google Classroom cousework assignment create grades uploaded

You can see that our new Assignment has been created with our title and description. We can also see that the marks have been assigned.

Click on View assignment to see the grading.

Google Classroom Uploaded Results of Assignment

Here you can see the Max points of 40 at the top under the title. And the two marked grades for our students.

Creating Just the Coursework Assignment

Perhaps you want to simply create the coursework for your Google Classroom so that you can show your students what is coming but upload the course results later.

To do this you can add this function to your project:

This will also log the coursework ID once the course is created so that you can keep a record of it to use it later when you want to upload the grades.

Check out the Quick Use Guide in the Uploading the grades section for details on how to make changes for your own project.

Uploading the Grades Only

If you already have the coursework built, you may only need to upload the grades. To do this, use the code below.

Just keep in mind that you must create the coursework in your Google Apps Script console instead of your Google Classroom dashboard.

Here you can see that we have copied our coursework ID we logged in our createCourseWorkItem() from the previous section and added it to our COURSEWORK_ID variable.

If you want to learn about how the code works, read on…

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro!

Got a more specific problem you need help with, but don’t have the time to develop the skills? Fiverr’s your best bet to find a skilled Google Apps Script professional to solve your problem quickly and cheaply. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

Code Breakdown Of Upload Process

In this code breakdown, we will go over the working parts of the assignGradesToNewCourseWork() function and its helper functions we haven’t yet covered.

You can pop out the code and follow along or just review the code snippets during the walkthrough.

assignGradesToNewCourseWork()

We have already covered our main variables in our quick guide. Let’s move down to line 27.

The COURSEWORK_ID variable deploys the createCourseWork_() function. This function takes two arguments:

  1. The course ID
  2. The course Info

This function creates a new course based on all the information you added to the COURSE_INFO object inside your selected course and returns the ID of the newly created course.

Next, on line 30, we collect the grades from the importGrades_() function.  The grades are returned as a 2d array of ID values (either student id or their email) and their corresponding grade.

Our importGrades_() function simply grabs the grades from a Google Sheet, however, you could import grades directly from an assessment API so that the entire process is automated.

Lastly, we loop through our GRADES array using the forEach method calling the setGrade_() function to upload the grades to our newly created coursework assignment. The setGrade_() function takes 4 arguments:

  1. COURSE_ID – the id of the course.
  2. COURSEWORK_ID – this was created when we ran our createCourseWork_() function.
  3. student[0] – this is the first item in the GRADES row which has the ID for the student.
  4. student[1] – this is the second item in the GRADES row which is the grade for the student.

That’s all there is to the assignGradesToNewCourseWork() run function.

createCourseWork_()

As the name suggests, the createCourseWork_() function builds a new coursework assignment for your selected Google Classroom course. This function takes two parameters:

  • COURSE_ID – The id of the course you want to add your coursework item to.
  • COURSE_INFO – The object containing all the information you need like the name of the course, description, max grade, etc.

The function then returns the new coursework assignment ID so it can be referenced later when uploading grades.

Our primary task occurs on line 11.

Here we use the Google Classroom API  Courses.Coursework resource and select the create method. This method takes our COURSE_INFO and COURSE_ID data as arguments.

This will build our new course work assignment. newCourseAssigmnet then becomes an object of the new coursework with all the assigned information to it. However, all we need from the newCourseAssigmnet course assignment is the id object which we call on line  13.

It’s probably a good idea for us to log the ID of the newly created course somewhere so that we can keep a record of it. We do this on line 15 before returning the ID so it can be used in our main run function.

setGrade_()

Our setGrade_() function uploads the grades to our coursework assignment. The function takes 4 parameters:

  • COURSE_ID
  • COURSEWORK_ID
  • USER_ID
  • GRADE

This function is called from the main assignGradesToNewCourseWork() run function each time it iterates through the list of GRADES.

We kick off by setting up a try…catch statement. This will make an attempt to upload a grade, but if an issue exists in the upload (most likely with the wrong user ID credentials) it will ‘catch’ it and then it will record the error to the console and log the userID that could not be uploaded (Lines 34-37).

The e parameter logs the error information that we will display with our console.error. We then log the user ID with a template literal which allows us to put our user ID inline with our text.

Back up to the top on line 12, we assign our GRADE to our grades object which contains an assigned grade and a draft grade.

These two keys represent the grades before it is returned to the student in the Google Classroom console and the final grade.  We may as well give the grade to both.

Next, we need to find all the student submissions, calling the StudentSubmissions resource in the Google Classroom API.

This resource contains a list of all the students in your course. Each item in the list is an object with key information containing things like the student’s ID, their grades (Both assigned and draft), whether they were late, etc.(Line 17)

With our resource in hand, we then need to find the submission ID for our currently selected user. We can use the Student Submissions list method to do this.

This method requires a course ID and coursework ID. We can also add an optional query parameter that will allow us to isolate a student by their email or google ID. From here we can then grab the id value for that user. This id is the specific coursework ID unique to that student.

Our final step is to add in the grade using the Student Submission resource again. We this time call the patch method.

The patch method can only be used on coursework that had been created by you programmatically. Luckily, we did this earlier.

Our patch will take 4 arguments. First, we will add our grades object with the grades for our assigned and draft grades. Next, we add the course ID, coursework ID and the submission Id we just collected. Finally, we need to tell patch what we need to update with updateMask.

Conclusion

Google Classroom API

I found that traversing the Classroom API to be quite challenging, particularly when translating it into the context of Google Apps Script. While the docs do shed some light on the capabilities of the API, it doesn’t have many examples using programming languages so that you can get an idea of the format.

On the bright side, when you add the API to your Google Apps Script project, it is kind enough to help out with word completion. However, the problem mostly lies in how you must apply the arguments inside methods. In other Google APIs you usually apply an argument one branch at a time so for example instead of something like this:

…to me, it would seem more intuitive to have something like this:

But that’s just me. There are really smart folks at Google making decisions for approaches I could not possibly comprehend, so I am cool.

I also liked the Try This sidebar that allows you to play with the API.

Try this Google Classroom support

Uploading Grades To Google Classroom

The code I have written in this example is fairly stripped down so that the process is as clear as possible. In my production code, I have put a lot more checks for potential errors. Some things you might want to consider are:

  • Greater than max grade check.
  • Grade is a number or a string containing a number check.
  • Connectivity check with Google classroom before running.

What other checks can you think of?

Anyway, I hope you found this tutorial useful. I really love hearing how these tutorials have been applied in other projects so please tell me about it in the comments below.

If you found this post useful, please consider subscribing (Top Right). I usually post twice a month and a bit more frequently in June and July.

Cheers,

Yagi

Full Code

Setup.gs

CourseGrades.gs

Test.gs

11 thoughts on “Google Apps Script: Upload grades into a Google Classroom Coursework Assignment”

  1. Great work sir!

    Thank you for keeping these posts relevant to current requirements and needs.

  2. Hi Yagi and friends.

    Question: How do I post an assignment with attachments where students receive a copy?

    Problem: I can get the materials posted in all shareModes except “STUDENT_COPY”.

    So I’m able to add materials: Example:
    “materials” : [
    ,{“link” : {“url” : “https://developers.google.com/classroom/reference/rest/v1/courses.courseWork/patch”}}
    ,{“driveFile”: {“shareMode”: “STUDENT_COPY”,”driveFile”: {“id”: “1eSd_fmsZSCL1jGPAayhXpID-D1ZDSaR7W0dOhkF8xEA”}}}
    // ,{“driveFile”: {“shareMode”: “STUDENT_COPY”,”driveFile”: {“id”: “1XG2upXRVG5yzhfs1OJgxiQU5tIfGrGupSRpir1_1eho”}}}
    ,{“youtubeVideo”: {“id” : “k_cj46u904s”}}
    ],

    but, I can’t seem to get the assignment to post with a copy for each student.

    I’ve attempted to create a student work folder, but with no success.
    Ex: “assignment” : {“studentWorkFolder” : {“id” : “1_qddMkFNeZFMBTCyGOhizn6Lr7xRKEPj”}},

    Reference: https://developers.google.com/classroom/reference/rest/v1/courses.courseWork/create

    Any suggestions?

    1. I hate replying to myself, but apparently there is a work around (not ideal), but it may work.

      You can add the scheduledTime name and add a few minutes, as noted in this Stackoverflow: https://stackoverflow.com/questions/58707261/internal-error-when-publishing-coursework-with-student-copies-in-google-classroo

      Time must be in UTC (Coordinated Universal Time) Zulu.
      Ex:
      “scheduledTime”: “2020-06-08T01:34:55Z”,

      A question I’m noodling:
      Say you want the document link for the assignment, so you can you use your nifty rubric grader, would you it make more sense to have a script that creates documents through an iteration function and post the link to the pre-designated folder in Classroom or create a map of the assignment drive URL after Google Classroom creates the document? 🤔

  3. Yagi, is it possible to filter the map by URL?

    I came up with the following code, but I cannot correctly filter the double array (if it is truly a double array) to pull only the array with the correct link:

    function findCourseByUrl() {
    const courseList = Classroom.Courses.list({“courseStates”:[“ACTIVE”]}).courses;

    Logger.log(data);
    };

    1. I figured it out…
      Some help from the following video: https://youtu.be/PT_TDhMhWsE

      /////////////////
      /////////////////
      /* Filter by URL
      /* 1st constant filters active courses when mapped
      /* return setup to create multidimensional array
      /* map is filtered looking for a specific URL link
      /* should return only one course with name, id, owner, URL
      */
      /////////////////
      /////////////////

      function findCourseByUrl() {
      const courseList = Classroom.Courses.list({“courseStates”:[“ACTIVE”]}).courses;

      let theCourse = courseData.filter(filterCourse); //this could be a return if called by function in Test.gs

      Logger.log(theCourse); //remove if using a function with console.log in Test.gs

      };

      ////////////////////////////////////////

  4. How did you find the classroom’s courseWork_id, title_id and all, please help me

Leave a Reply