Revisiting issuing Mozilla Open Badges with Google Apps Script and Google Sites: Notes on new options

Back in 2012 I shared some of the exploratory work I did issuing Mozilla Open Badges with using a combination of Google Apps Script and Google Sites. This solution had bit of a fudge which required the badge Assertion (the JSON data file behind each individual badge), to be proxied via a web host. It was great to see this post was followed up by David Mullet who was able to add some additional functionality as well as avoiding the badge proxying. Since then I’ve also revisited Open Badges, this time as an add-on to issue badges from self-hosted WordPress sites. As part of this I learned more about issuing badges and in particular the Mozilla Issuer API. The Issuer API is a JavaScript library which makes it easy for you to let people add badges they’ve achieved to their badge portfolio in the Mozilla Backpack. Late last year I decided to revisit Open Badges and Apps Script, this time integrating the Issuer API into a Script powered web app, removing the need send people to a Google Site. This wasn’t as straight forward as I had anticipated and but in this post I’ll cover what is possible.


Survey participant emailSo why issue badges directly from Google Apps Script? This was inspired by feedback from a survey we were running at ALT. This was distributed as a Google Form. To help improve the response rate we included a feature to receive an email confirming the respondent’s participation in the survey. The confirmation, sent using Apps Script, included a suggested tweet and a digital badge for them to display highlighting participation. Because the badge wasn’t in the Open Badge format respondent’s couldn’t add it to their Mozilla Backpack. I could have of course reused the earlier work I and David have done on issuing badges via Google Sites, but wanted to see if it was possible to remove that dependency and issue Open Badges from a single container bound script or by embedding an Apps Script in Google Sites.

What’s possible?

Looking through the source code of the Issuer API you can see it has two methods for launching a badge claim interface. The default, OpenBadges.issue (code here) is a full screen modal interface created by injecting a iframe. The fallback, OpenBadges.issue_no_modal (code here), adds the badge data to a web form which is automatically submitted to the Backpack to handle. At the time I was exploring this problem, the method for creating html based interfaces in Apps Script was restricted to a sanitised version of HTML which didn’t support the modal/iframe way of doing things. That all changed in December when Google announced an alternative way of serving HTML in Apps Script that skipped most on the sanitisation (see Speeding up HtmlService in Apps Script).

This all sounds promising, directly wrapping the Issuer API JavaScript library in a Apps Script powered web app. Trying this out I hit my first issue:

I’m using Google Apps Script Content Service to generate a badge assertion (1.0.0 spec), example here

When trying to issue the badge using the Issuer API the issuer returns a 504 bad gateway example header response. Using Google Apps Script Content Service there are 302 redirects are in place for the badge assertion which end in 200 OK (this is how Google configure their service). Here is example 302 redirect headers and example eventual 200 OK.

Using Google Apps Script Content Service to create badge assertions appears to only affect assertions that include verify.url (a 0.5.0 spec assertion is issued without issue).

A 302 redirect 1.0.0 spec assertion was issued okay e.g. which suggests something else in the headers is causing the 504 bad gateway

If you fill in this form with your Backpack email it sent a link to a Google Site where you should be able to claim a badge associated to your email

I’m still getting a 504

A lot to take in here. Basically Open Badges can use a JSON object for each badge also known as the Assertion.  The Assertion spec is at 1.0 which requires  a verification url for the badge. The verfication url is the same as the url where the Assertion lives. Here is an example badge generated using Apps Script:

Now if you hit the verify.url: "" you get passed through a 302 redirect:

302 redirect

In terms of Badge Verification “eventual 200 OK” is permitted:

The use of the term “eventual 200 OK” is meant to mean that 3xx redirects are allowed, as long as the request eventually terminates on a resource that returns a 200 OK.

Using the Open Badges Validator throwing in the verify.url returns a valid Assertion

valid Assertion

So the Mozilla Backpack issue ticket remains open. Currently, as far as I can see, a version 1.0 spec Assertion generated in Apps Script 504s in the Issuer API. If you are desperate to issue Open Badges in Apps Script NOW!!! the fix ain’t pretty … the Open Badges 0.5 spec assertion (bloody nightmare to find this reference …). This is basically where I was in 2012, a badge assertion that doesn’t use a verify.url.

Lets however look at a couple of example workflows for issuing Open Badges using Google Apps Script.

Example: Using a Google Form to Issue Open Badges via a Google Site

Back to the original scenario of giving someone an open badge for completing a Google Form.  Here’s an example Form/Sheet you are free to copy/reuse. Things to note are:

  • an extra sheet called IssuedBadges; and
  • some code in Tools > Script editor (source extracted into a gist) which needs you to go to Resources > Current project’s triggers and add a onSubmit trigger .

The code is hooked into the form submission and records a new badge in the IssuedBadges sheet and generates an email to the recipient to collect their badge (note current issue with duplicate emails from Apps Script). You’ll also see from the code it includes a BASE_URL, this is the place we’ll send people to  collect their badge. A Google Site can happily have a container bound Apps Script, but in this example I want to highlight how you can have a standalone script embedded in a Google Site. So our next bit of code is a standalone Google Apps Script which handles the Open Badges Assertion creation and issuing. You can copy and then modify the standalone script here or browse as a gist).

Hopefully the source has enough in-line documentation to make sense of it. Basically the code looks for the type of data it’s returning. If it’s another machine it throws JSON and for humans shows the Mozilla Issuer API which will help the person collect their badge in the url.  To deploy this code we need to publish it as a web app. If you haven’t done this before from your copy of the script in the Script Editor select Publish > Deploy as web app which should give a similar dialog to the one below:

Deploy as web app

A couple of neat things here. For this to work you need to allow the app to ‘execute as me’. This lets the script access the Google Sheets your account can access. This means the script will selectively be able to read the Google Form responses you get. We also allow the script to run for anyone, even anonymously. This doesn’t mean that anyone can start reading all of your data, the script is programmed only to ready specific data and only return a specific interface designed by us.

When you hit ‘Deploy’ this gives you a ‘service url’. You can try this url and you’ll get a browser window with something like:


Back at the script attached to your Sheet/Form you could replace the BASE_URL with ‘service url’ (this line of code). So when someone fills in your form they will get an email to your deployed script which will have the extra bits needed in the link to issue them a badge. This isn’t great UX so instead lets see how you can use the same url in a Google Site, the advantage being you can provide additional information about collecting a badge in a Google Site. Fortunately the Google Developers site has some great guidance on Embedding your web app in Google Sites which should allow you to paste in your ‘service url’.

You can adjust the gadget settings like size and border, and of course add extra information. To see all of this in action enter your email in the form below and you should get an email with a ‘claim link’ to the ‘sandbox’ site (emails won’t be shared or used for any other purpose than sending the claim url).

Wrapping up

So if you’ve made it this far !!!WELL DONE!!! (#epic). Some things to note. This example currently only works with 0.5 spec Open Badge Assertions. Hopefully the 504 issue with Backpack/Issuer API is resolved. Some of you may have noticed that in this example I opted to use the issue_no_modal of the Issuer API rather than take full advantage of the new Apps Script IFRAME/modal mode. The reason I didn’t is there are some open issues with IFRAME and Caja’d version using no_modal Issuer API works perfectly fine (I’ve left the iframe version in the code if you prefer this way).

Enjoy and as always comments to clarify any of this are welcome