Skip to Content
Personal Insights
Author's profile photo Sven Haiges

NFC comes to the web

It must have been around 2012, when Google launched the first NFC-enabled phones (Google Nexus S) together with an update to Android that did allow developers to use the NFC APIs. I can well remember to pay a few euros for just a few NFC tags to play around (these tags cost very little today…). While I’ve been super convinced and the CX Labs team announced many prototypes such as NFC shopping at that time, it took many years for Apple to adopt NFC and finally also open up the APIs to their developers. NFC was almost forgotten… But it’s now 2021 and most phones have NFC hardware built in. The primary use case is payments, NFC card emulation is one of the three operating modes of NFC and most of us use Apple or Google pay on a daily basis.

This means, that NFC functionality is widely available to to devs out there, but to be frank, it’s not very often used besides via the Google/Apple maintained payment apps. But just in May 2021 Chrome for Android 91 came out and now supports Web NFC – any web developer can experiment and use NFC from simple HTML pages. While once more Apple’s Safari and other browsers are late to the game, it could again mark a moment in time for another breakthrough for NFC technology. Web NFC lowers the barrier to play for the developers and – more importantly – NFC functionality can now be part of the web: no installations.

Web NFC 101

NFC stands for Near Field Communications and is a short range wireless technology operating at 13.56 MHz. Short range really means short range: in order to communicate, the devices have to be just a few centimeters apart. There are four operating modes defined by the NFC Forum: reader/writer, peer-to-peer, card emulation and wireless charging. Of these four modes, only the first one – reader/writer – and only the so-called NDEF specification is supported by Web NFC. NDEF is the NFC Data Exchange Format and describes a standardized way to encode data onto NFC tags and read it back. For example, it defines how text is encoded or how URLs can be encoded in a byte-saving manner.

So just be clear: you will not be able to emulate a credit card with NFC for in-store payments, nor will you be able to “turn on NFC wireless charing” via Web NFC. But everything that deals with reading and writing little snippets of data to NFC tags in the standardized NDEF format is in.

Potential Customer Experience Use Cases

The Web NFC spec itself lists a few use cases such as using NFC tags in art galleries or museums. I must admit that I don’t see the clear benefit in many cases. These tags could well be written with a special NFC phone and app and the users of these tags would simply touch the tags to open up web URLs – that’s state of the art today. I believe that Web NFC can play a role, especially in CX, when it comes to use cases for which customers would never install an app for these days. For example, to participate in a gamified experience in a retail store, I would not install an app – but I might be willing to open up a web page to participate. Web NFC also supports writing NFC tags which opens up some interesting application fields for service technicians for example. While a service area can be identified with the NFC tag, now the exact date/time a machine was serviced could also be written back to the tag. All that is possible, without requiring a special app to install, which lowers the barriers to entry.

To experiment with Web NFC on my Pixel 5 and the Chrome Browser, I created a small public web page which you can also use to try it out. The following code examples are all taken from there. Web NFC and also the NDEF standard for understanding the messages written or read from NFC tags can be found in the official spec.

Hands on – writing tags

To write to an NFC Tag, you need to understand the structure of an NDEF message. The message which is written to a tag is composed of multiple NDEFRecords – which can be plain text, URLs or more complex types such as smart posters.

As you can see, writing a simple text message is trivial:

document.getElementById("write").addEventListener("click", async () => {
   log("writeLog", "User clicked write button");
 try {
     const ndef = new NDEFReader();
     await ndef.write("Hello Office of the CTO!");
     log("writeLog", "> Text Message written");
   } catch (error) {
     log("writeLog", "Argh! " + error);
   }
 });

Let’s now write a URL to the tag, which requires us to list the records of the message – here we only use one URL record:

document.getElementById("writeUrl").addEventListener("click", async () => {
  log("writeUrlLog", "User clicked write button");

  const ndef = new NDEFReader();
  try {
    await ndef.write({
      records: [{ recordType: "url", data: "https://cxlabs.sap.com" }]
    });
    log("writeUrlLog", "> URl Message written");
  } catch {
    log("writeUrlLog", "Argh! " + error);
  }
});

Hands on – reading tags

Reading tags can be more challenging, as you have to differntiate between the different records that you might find. My example tries to deal with a few common cases such as text, URLs but also JSON-encoded data, which of course would have a specific structure that your app needs to know about:

document.getElementById("read").addEventListener("click", async () => {
  log("readLog", "User clicked read button");

  try {
    const ndef = new NDEFReader();
    await ndef.scan();
    log("readLog", "> Scan started");

    ndef.addEventListener("readingerror", () => {
      log(
        "readLog",
        "Argh! Cannot read data from the NFC tag. Try another one?"
      );
    });

    ndef.addEventListener("reading", ({ message, serialNumber }) => {
      log("readLog", `> Serial Number: ${serialNumber}`);
      log("readLog", `> Records: (${message.records.length})`);

      const decoder = new TextDecoder();
      for (const record of message.records) {
        switch (record.recordType) {
          case "text":
            const textDecoder = new TextDecoder(record.encoding);
            log(
              "readLog",
              `Text: ${textDecoder.decode(record.data)} (${record.lang})`
            );
            break;
          case "url":
            log("readLog", `URL: ${decoder.decode(record.data)}`);
            break;
          case "mime":
            if (record.mediaType === "application/json") {
              log(
                "readLog",
                `JSON: ${JSON.parse(decoder.decode(record.data))}`
              );
            } else {
              log("readLog", `Media not handled`);
            }
            break;
          default:
            log("readLog", `Record not handled`);
        }
      }
    });
  } catch (error) {
    log("readLog", "Argh! " + error);
  }
});

Summary

At this point, Web NFC is only available on Android phones via the Chrome browser. I had to wait multiple years when NFC first came to native android for Apple to catch up, so I’ll definitely not try to predict when most browsers on most mobile OSes will suport Web NFC. But I must say that the simplicity with which web developers can now use physical NFC tags is amazing – I am pretty sure this will spark a lot of creative ideas. For sure there will be uses cases also in the area of customer experience and it’s also clear that the web as a platform will continue to rise. We’ll keep a close eye on Web NFC and for now have found a great new API that we can start using as of today.

Assigned tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.