跳到正文
DEV Community· Pocket Factory·· 4 小時前AI 評分36

如何將 Google 評論連結寫入 NFC 標籤(NTAG213/215/216),並準備 QR code 備用方案

Writing a Google review link to an NFC tag (NTAG213/215/216) with a QR fallback

AI 導讀

文章説明如何用 JavaScript 和 Android Web NFC,將 Google 商家檔案的評論連結寫入 NTAG213、NTAG215 或 NTAG216 NFC 標籤,並以開源程式庫製作 QR code 備用方案。三款標籤的用戶記憶體分別為 144、504 和 888 bytes;文中的 79 字元範例連結可寫入全部三款。

正文

Plenty of small businesses want a "tap here to review us" card or sticker at the counter. Doing it yourself takes a few dozen lines of JavaScript, a few cheap NTAG stickers and an Android phone. You do have to watch a few details: which URL you write, whether it fits on the chip, whether you lock the tag, and what happens when someone's phone has no NFC.

This post covers:

  1. Getting the review link (and the writereview URL format)
  2. NDEF byte math: will the URL fit on an NTAG213, 215 or 216?
  3. Writing the tag from a web page with Web NFC (NDEFReader)
  4. Locking the tag read-only
  5. Testing on iPhone and Android
  6. Generating a QR fallback with an open-source library
  7. Google's review rules in plain words

Disclosure: I run a small shop that sells pre-programmed NFC cards (details at the end). Everything below works with any blank NTAG tag and free tools.

1. Get the review link

The official way

Google Business Profile gives you the link directly. Google's help article Create a Google link or QR code to request reviews describes it: open your Business Profile, choose Read reviews → Get more reviews, then Copy the link or save the QR code. The same page notes that review QR codes can currently only be generated from a computer browser, not a phone.

Use this link if you can. Google issues it, it points at your profile, and it's short, which matters for NFC (see section 2).

The writereview URL (backup option)

You'll also see this format used all over the web:

https://search.google.com/local/writereview?placeid=YOUR_PLACE_ID

It opens the "write a review" box for the place with that Place ID. Two caveats:

  • Google's review-link help page doesn't document this format. It's widely used and it works today, but it's community knowledge, not a promise. If Google changes it, every tag you've written with it breaks.
  • You need the right Place ID. Google's Place ID page has a finder; search your business name and copy the ID exactly. Google says a truncated or modified Place ID is invalid, and that Place IDs can change over time.

My suggestion: write the link Business Profile gives you. Keep writereview as a fallback for when you can't get into the profile (for example, you're setting up a tag for a friend's shop).

Before writing anything, open the link on a phone that's not signed in as the business owner. You should land on the review form or the profile with a review button, not on a sign-in wall or a "page not found."

2. Will it fit? NDEF byte math

NTAG213, 215 and 216 have 144, 504 and 888 bytes of user memory, per NXP's NTAG213/215/216 product documentation. A URL is stored as an NDEF URI record, wrapped in a TLV block. For a short URL, the bytes look like this:

03 LL                 TLV: type 0x03 (NDEF message), length LL
D1 01 PL 55           record header: MB+ME+SR, TNF=1 (well-known), type length 1, payload length PL, type "U"
04                    URI prefix code (0x04 = "https://")
67 2E 70 61 ...       the rest of the URL as UTF-8 ("g.pa...")
FE                    terminator TLV

The URI record type replaces common prefixes with one byte. The four you'll use:

Code Prefix
0x01 http://www.
0x02 https://www.
0x03 http://
0x04 https://

So for a short record the overhead is 2 (TLV) + 4 (header) + 1 (prefix code) + 1 (terminator) = 8 bytes. The https:// prefix is 8 characters and gets replaced by that one byte, so for an https:// URL the bytes on the tag come out equal to the URL's length (4 fewer if it starts with https://www., which has its own prefix code). On an NTAG213 that means an https:// URL of up to 144 characters fits.

Two thresholds add bytes on long URLs: once the record passes 254 bytes, the TLV length field grows to 3 bytes (+2), and once the payload passes 255 bytes, the record switches to the long format with a 4-byte payload length (+3). That only matters for NTAG215/216 and very long URLs.

Here's a helper that does the math:

// NFC Forum URI record prefixes we care about (index = prefix code)
const PREFIXES = ["", "http://www.", "https://www.", "http://", "https://"];

function ndefUriBytes(url) {
  // pick the longest matching prefix
  let code = 0;
  for (let i = 1; i < PREFIXES.length; i++) {
    if (url.startsWith(PREFIXES[i]) && PREFIXES[i].length > PREFIXES[code].length) code = i;
  }
  const rest = url.slice(PREFIXES[code].length);
  const payload = 1 + new TextEncoder().encode(rest).length; // prefix byte + URL bytes
  const header = payload <= 255 ? 4 : 7;                      // short vs long record
  const record = header + payload;
  const tlv = record <= 254 ? 2 : 4;                          // 1-byte vs 3-byte TLV length
  return tlv + record + 1;                                    // + terminator 0xFE
}

const CAPACITY = { NTAG213: 144, NTAG215: 504, NTAG216: 888 };

const url = "https://search.google.com/local/writereview?placeid=ChIJxxxxxxxxxxxxxxxxxxxxxxx";
const bytes = ndefUriBytes(url);
for (const [chip, cap] of Object.entries(CAPACITY)) {
  console.log(chip, bytes <= cap ? `fits (${cap - bytes} bytes left)` : "too big");
}

That example URL is 79 characters and needs 79 bytes, so it fits on all three chips. Review links are short, so an NTAG213 is enough almost every time. Pick 215 or 216 only if you plan to store something else alongside the URL.

One thing the math doesn't cover: whether your writing tool actually uses the prefix code. Most do, but check what landed on the tag with a reader app (section 5).

3. Write the tag from a web page (Web NFC)

Web NFC launched in Chrome 89 for Android. It doesn't exist on iPhone or desktop browsers, so the writing step needs an Android phone. Per Chrome's docs, it only works:

  • on HTTPS pages (or localhost), in a top-level frame,
  • when called from a user gesture like a button click,
  • while the page is visible and the phone is unlocked.

A minimal writer page:

<input id="url" type="url" placeholder="https://..." size="60">
<button id="write">Write tag</button>
<p id="log"></p>

<script>
const log = (msg) => (document.getElementById("log").textContent = msg);

document.getElementById("write").addEventListener("click", async () => {
  if (!("NDEFReader" in window)) {
    log("Web NFC isn't available here. Use Chrome on Android over HTTPS.");
    return;
  }
  const data = document.getElementById("url").value.trim();
  try {
    new URL(data); // throws on a malformed URL
  } catch {
    log("That doesn't look like a full URL.");
    return;
  }
  try {
    const ndef = new NDEFReader();
    log("Hold the tag against the back of the phone...");
    await ndef.write({ records: [{ recordType: "url", data }] });
    log("Written. Now test it with a different phone.");
  } catch (err) {
    log(`Write failed: ${err.name}: ${err.message}`);
  }
});
</script>

Notes:

  • Use recordType: "url", not "text". A text record shows the URL as text; it doesn't open it.
  • write() overwrites whatever is on the tag by default. If you're writing a batch and want to skip tags that already have data, pass { overwrite: false } and the promise rejects if the tag already holds an NDEF message.
  • The browser asks for NFC permission the first time.
  • Where the antenna sits varies by phone. If nothing happens, slide the tag slowly around the back of the phone.

4. Lock the tag (optional, permanent)

A tag sitting on a counter can be rewritten by anyone with an NFC app, unless you lock it. Chrome 100+ on Android adds makeReadOnly():

<button id="lock">Lock tag (permanent)</button>

<script>
// reuses log() from the writer page above
if ("NDEFReader" in window && "makeReadOnly" in NDEFReader.prototype) {
  document.getElementById("lock").addEventListener("click", async () => {
    try {
      const ndef = new NDEFReader();
      log("Hold the tag against the phone to lock it...");
      await ndef.makeReadOnly(); // resolves after the user taps the tag
      log("Tag is now permanently read-only.");
    } catch (err) {
      log(`Lock failed: ${err.name}: ${err.message}`);
    }
  });
} else {
  document.getElementById("lock").disabled = true; // needs Chrome 100+ on Android
}
</script>

This can't be undone. Only lock a tag after you've tested it on both platforms and you're sure the URL won't change. If you think you might switch links later, leave it unlocked, or point the tag at a URL on your own domain that redirects to Google, so you can change the destination without touching the tag. Keep the redirect a plain redirect, with no rating screen in between (see section 7).

5. Test on iPhone and Android

Android: NFC has to be switched on in settings. With the screen on and unlocked, a tap on a URL tag opens the link.

iPhone: According to Apple's background tag reading docs, iPhone XS and later read NDEF tags in the background, without an app, while the iPhone is in use (screen on). Apple lists exceptions: not before the first unlock after a restart, not while Apple Pay, Wallet or the camera is in use, and not in Airplane Mode. A banner appears and tapping it opens the URL. Older NFC-capable iPhones (7, 8, X) don't read tags in the background; they need the NFC Tag Reader control in Control Center (iOS 14 or later) or a reader app. Phones without NFC can't tap at all, which is what the QR fallback in section 6 is for.

A checklist I use:

  1. Read the tag with a reader app (NXP's TagInfo or NFC Tools) and confirm the record is a URI record with the exact URL, with no extra spaces or a stray http:// prefix.
  2. Tap with an Android phone that has never visited the link.
  3. Tap with an iPhone XS or newer, unlocked.
  4. Tap through a phone case and, if the tag will be stuck on something, on that surface. Metal behind an ordinary tag can stop it from reading; use on-metal tags there.
  5. Do it signed out of Google, so you see what a customer sees.

6. QR fallback

Some phones don't have NFC, some have it switched off, and some people just don't know to tap. Put a QR code of the same URL next to the tag.

The node-qrcode library (MIT licensed) does this in a few lines:

npm install qrcode
const QRCode = require("qrcode");

const url = "https://search.google.com/local/writereview?placeid=ChIJxxxxxxxxxxxxxxxxxxxxxxx";

// PNG for quick printing
QRCode.toFile("review-qr.png", url, { errorCorrectionLevel: "M", margin: 4, width: 600 });

// SVG for print shops (scales without blurring)
QRCode.toString(url, { type: "svg", errorCorrectionLevel: "M", margin: 4 })
  .then((svg) => require("fs").writeFileSync("review-qr.svg", svg));

Tips:

  • Keep the quiet zone (margin: 4). Cropping the white border is the most common reason printed codes won't scan.
  • Dark modules on a light background. Inverted codes fail on some scanner apps.
  • Don't print it tiny. Test-scan the printed code from the distance people will actually stand.
  • Add a short line like "Tap or scan to leave a review", so people know both options exist.
  • Google's Business Profile can also give you a ready-made review QR code (from a computer browser), if you'd rather not generate one.

For more on how tap cards behave on different phones, I wrote up which phones read NFC review cards and why some don't.

7. Google's review rules in plain words

The tech is the easy part. What gets reviews removed is how you ask. From the Maps user-generated content policy and the review link help page:

  • No incentives. No payment, discounts, or free goods or services in exchange for a review, or for changing or removing a negative one. Google calls this fake engagement, and those reviews get removed.
  • No gating. Don't ask only the customers you think are happy, and don't put a "How did we do? 1–5 stars" screen in front of the link that sends only 4–5 star people to Google. Google doesn't allow merchants to "selectively solicit positive reviews."
  • Don't pressure or script. Don't require a review on the spot, don't tell people what to write, and don't give staff review quotas.
  • Do ask everyone the same way. Hand the card to every customer, or leave it at the counter. That's fine and it's what Google's own help page suggests (receipts, thank-you emails, a QR code in the store).

In practice: write the plain review URL to the tag, with no intermediate rating page, and offer it to everyone.

Wrap-up

  • Get the link from Business Profile → Get more reviews. writereview?placeid= is a backup.
  • For https:// URLs, the bytes on the tag ≈ the URL length. NTAG213 = 144 bytes.
  • NDEFReader.write({ records: [{ recordType: "url", data }] }) on Android Chrome 89+.
  • Test on both platforms, then makeReadOnly() (Chrome 100+) if you won't need to change the URL.
  • Print a QR code of the same URL as a fallback.
  • No incentives, no gating.

If you'd rather not program tags yourself

I run Pocket Factory, which makes personalized NFC cards with your logo, pre-programmed with your link (a Google review link, booking page, website or menu). They use an NTAG215 chip and ship locked, so the link can't be changed later; a new link means new cards. No battery or charging is needed, and a printed QR backup is included by default. The DIY route above works just as well if you have an Android phone and some blank tags.

If you build a small writer page from this, I'd like to hear what tags and phones you tested on.

來源:DEV Community · dev.to