23/2/2024
10 min read

Why did the NZ COVID Tracer Poster use a QR code?

The choices that lead to 804,000,000+ successful scans.
Aaron Yee
Principal Consultant
Header image

On 25 March 2020 New Zealand went into Level 4 lockdown. The New Zealand Government sought a digital solution that would enable New Zealanders (once back out in the community) to privately track the places they had visited, and get notified if they had been in close contact with someone with Covid-19.

There were two parts to the solution: Tracking poster & Mobile scanning app/notification system.

Aaron Yee (Transition Digital) was the technical lead of the tracking poster. This article does a deep dive into the constraints, analysis and decisions made for deploying a barcode into the public domain that was successfully scanned 804 million times.

Key Takeaways (TLDR)

  • QR code was chosen as the barcode of choice because of its native supportability on mobile devices and large selection of optimised scanning libraries in addition to a high degree of error correction.
  • QR Code version 13 with ECC level M was chosen as it best balanced the amount of data that needed to be in the code, high levels of error correction and mobile device scannability.
  • QR codes supported Macrons to allow for Māori Business Names, Street Addresses and other special characters.

Constraints & Considerations

This poster/barcode was formed within the following constraints and considerations:

  • Digital inclusion - To the maximum extent possible the barcode had to be scannable on all mobile devices no matter the age of the phone and on the worst possible cameras.
  • Privacy - As check-in data was to be stored solely on citizens' devices, the barcode needed to contain all the required data and not simply be a poster ID that could be looked up through a secondary API service.
  • Scannability/Error correction - To the maximum extent possible the barcode needed to be scannable if damage occurred to posters such as discolouration, tearing or water damage.
  • Macrons - The barcode had to store data containing special characters like macrons.
  • Data & Offline Support - The data included inside the barcode needed to contain: Location ID (GLN), barcode version, type, company name, physical address.
  • Timing - The solution needed to be live within 2 weeks.
  • Barcode Size - The barcode needed to be scalable for large posters through to tiny QR codes on business cards and food menus.

Analysis - Deciding on the barcode type

what types of barcodes were looked at?

Analysis was done by looking at three different barcode types:

  • GS1 Datamatrix
  • QR Code
  • Aztec Code

Macrons & special characters

GS1 Datamatrix - The GS1 Datamatrix did not support special characters such as ā, ē, ī, ō, ū from the Māori language. A later decision to encode the data with base64 would have avoided the technical need for the barcode to support this. However this also neglected one of GS1's biggest selling points that their codes were "human readable"

source: https://www.gs1.org

QR Code - Supported Macrons and special characters, for example "ō", required around the same data storage space as having two o's eg: "oo". This was a non-material difference and was considered when deciding on the QR code version.

Storing Data in the code

As a goal was to maximise privacy for New Zealand citizens, the barcode was required to contain all the check-in data (like someone writing down where they were in a private notebook). Upon scanning, mobile phones would simply log the data in the mobile app instead of being required to do any secondary API lookup.

A JSON schema was used as it offered maximum flexibility for both the poster generation team and the mobile app development team to easily use modern libraries to encode, decode and use the required data.

{
"gln": "9420000000000",
"ver": "c19:1",
"typ": "entry",
"opn": "Business Name",
"adr": "Street Number\nStreet Name\nCity"
}

For data integrity reasons the JSON key-value pair was encrypted as base64.

NZCOVIDTRACER:eyJnbG4iOiI5NDAwMDAwMDAwMDAiLCJ2ZXIiOiJjMTk6MSIsInR5cCI6ImVudHJ5Iiwib3BuIjoiS2Fpa8WNdXJhIEJha2VyeSIsImFkciI6IjE2IFN0cmVldCBOYW1lXG5Sb2FkIE5hbWVcbkNpdHkgTmFtZSJ9

GS1 Datamatrix - Under the GS1 Datamatrix the data must be structured according to the rules of the GS1 System. These can be found in GS1's 501 page GS1 general specifications document. For example:

(01)03453120000011(17)191125(10)ABCD1234

The way the data format works is that (01) (17) (10) represent identifiers from the GS1 index table. This makes the code "human readable" where humans would know or be able to refer to the index:

(01) = a 14 digit GTN

(17) = an expiration date of 25 Nov. 2019

(10)  = Batch Number

A couple of challenges with the GS1 datamatrix option:

  • We would have needed to adopt the GS1 standard instead of following a JSON schema.
  • There weren't direct identifiers for the types of data values required to be captured for our scenario. There was the potential to use custom identifiers but even these had length limitations.
  • There were no readily available Java support libraries to generate codes in the GS1 Datamatrix format and the form builder team would have had to construct the GS1 datamatrix data as a string and concatenate the values.
  • There was no native support and no readily available libraries for iPhone and Android that could be easily used by mobile app developers.

QR Code - There was no specific standard to follow, meaning it was possible to inject the the base64 JSON schema into the QR code without any issues. Within hours the team at the Ministry of Health who were developing the mobile application were able to generate a website to test the reading of the code and present the encoded data. Support for QR decoding is also offered natively within Webapps, Apple and Android libraries for QR code reading.

Error correction in the code

Error correction inside barcodes allows for the code to still be scannable, even if there are issues with the code. For example poor printing, light reflection at time of scanning or being damaged from water/folding/tearing. All of these could be entirely possible as codes would be deployed throughout New Zealand so error correction was of vital importance.

Both the GS1 Datamatrix and QR code generation follow the Reed-Solomon Code for data correction and dynamically range from approximately 7% to 30% of correction.

Datamatrix: "The size of the Data Matrix symbol is determined by the amount of data to be encoded and not on the desired percentage of error correction."

QR Code: Testing undertaken showed that the QR code version could be specified, which in theory would allow a higher percentage of data correction to be generated into the code. More on QR code versions can be found here.

Source: https://blog.qrstuff.com/general/qr-code-error-correction

Digital Inclusion

QR code was the most supported native barcode reader that would be compatible with the oldest mobile devices. This paired with forcing a high Error Correction (ECC) means we could include almost all New Zealanders that had a mobile device.

Code Clashing & Fake Malicious Codes

Some consideration went into analysing if businesses had multiple codes close to each other, then the scanner may process the incorrect code or the possibility for malicious codes to navigate users to bad websites. In real life every New Zealander was told to download the app and to scan the code within the app. This meant that if the code contained anything other than the defined format of NZCOVIDTRACER, it would come up with a message that says invalid code and a citizen could move closer to the poster and try again.

QR Code

As a result of the findings above the decision was made to go with the QR code as the barcode of choice for the NZ COVID tracer poster. The next step was to decide on the QR code version and do some preliminary testing.

Working out the Min and Stretch Max data requirement

To work out which QR code version to use, an analysis was performed regarding the potential minimum (116 characters) and maximum (282 characters) data requirements that needed to be stored inside the code.

This gave a theoretical range of 116-282 alphanumeric characters and one ":" character.

Some future-proofing was added into the code just in case additional parameters needed to be introduced at a later date. This was called the "Stretch Max" with a length of 330 characters.

Selecting the QR code version number

At first when looking at the type of data that needed to be encoded, it was thought that the below base64 data string was mostly alphanumeric.

NZCOVIDTRACER:ewoJImdsbiI6ICI5NDI5MDQxMTk4Nzk3IiwKCSJ2ZXIiOiAiYzE5OjEiLAoJInR5cCI6ICJlbnRyeSIsCgkib3BuIjogIlRoZSBXYXJlaG91c2UgR3JvdXAg4oCTIFdlbGxpbmd0b24gQ2kiLAoJImFkciI6ICIxNjIgVGF1bWF0YXdoYWthdGFuZ2loYW5nYWtvYXVhIHVvdGFtYXRlYXR1cmlwdWtha2FwaWtpbWF1bmdhaG9yb251a3Vwb2thaXdoZW51YWtpdGFuYXRhaHUiCn0=

So using a look-up tables with a  stretch max of 330 characters it was assumed that the best version number was going to be version 11.

However...

When attempting to generate the stretch max code at this version number there were issues.

Turns out Alphanumeric characters are limited to the following:

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ, a space character “ “ and other letters $%*+-./:

The data requirements included lowercase characters which means binary mode must be used for any lowercase letters. Based on this, the data table was consulted once again.

Version 13 looked to be the new best version number to use.

Version 13 the code built successfully

Online or offline library to generate the QR code

There are so many different ways to generate QR codes. A massive amount of online APIs including Google QR code generator. The thought was that it was best not to be reliant on the availability of these 3rd party services.

It was decided that the open-source library bwip-js created by Metafloor was the best option. The advantages were:

  • Barcode support - This library supports generating barcodes in 100+ different formats including QR and GS1 Datamatrix. With a single parameter change, the barcode generation type could be switched.
  • Speed and Security - The library provided a API, Web demo & the ability to deploy the library within the application allowed speedy development using web interfaces before making the integration into the application.

Testing the code in real life

The Ministry of Health undertook robust testing of the posters but some preliminary testing was carried out prior to this.

The printer was running low on toner.. Pasted on the fridge using Aaron's parents as guinea pigs, they were able to successfully "check in" to their fridge.

Summary

There was a considerable amount of thinking that went into choosing the barcode type for the NZ COVID tracer poster and ensuring its robustness when deployed into the wild.

If you're navigating the complexities of QR code technology for your project, consider reaching out to Aaron or the team at transition.co.nz.