← Plugin catalog
Productivity

CodeQR - Link and QR Analytics

CodeQR v2.0.0

Publisher description

From the marketplace listing

CodeQR creates short links and QR codes that stay editable after they are printed or shared. Each code encodes a short link instead of the destination itself, so you can change where it leads without reprinting anything, and every scan and click is recorded with time, country, and device. It fits work where a code has to outlive the moment it was made: one code per property listing, per customer, per certificate, per job posting, or a printed campaign whose landing page moves. Your agent can create short links and QR codes on your own domain or a shared one, change where an existing code points, list codes it made earlier, and pull scan, click, lead, and sale analytics for one code or for the whole workspace.

Language: English · Automatically detected from descriptions.

Files & skills

File archives

Plugin package10 files · 8.36 KBBrowse files →
Skill instructions
bulk-qr-codes4.9 KB

View saved version →

---
name: bulk-qr-codes
description: Create a dynamic QR code or trackable short link for every row of a list, spreadsheet, or CSV in CodeQR, using predictable keys so any of them can be re-pointed later without reprinting. Triggers on bulk phrasing such as for each, every, one per, or a pasted list of destinations. Not for a single one-off code, not for reading or decoding an existing QR image, and not for offline or static QR generation.
---

# Bulk QR codes and short links

Create one CodeQR destination per row of a list, so the whole set can be measured
and re-pointed later without reprinting anything.

Do all of this through the CodeQR MCP tools. Never generate a QR image locally and
never call the CodeQR REST API directly: the connector already holds the user's
authorization, and a locally generated image cannot be re-pointed or measured,
which is the entire reason to use this workflow.

## Choose one resource type

- **Dynamic QR code** — `create_qrcode`. Use when the destination will be printed:
  signage, packaging, menus, labels, property boards.
- **Short link** — `create_link`. Use when the destination will be sent, posted,
  or clicked.

If the user has not said which, ask once. Do not create both for the same row.

## Before creating anything

1. Read the source list. Extract per row: the destination URL, and a label that
   identifies the row (property name, job title, product SKU).

2. Derive a `key` for each row from its label — lowercase, ASCII, words joined by
   hyphens, no spaces — prefixed with a short batch name shared by the whole set,
   for example `spring-menu-01`, `spring-menu-02`.

   The key is how the user finds and re-points one specific code months later.
   Omitting it gets a random 7-character slug and defeats the workflow, so always
   set it.

3. Show the row count and the **first two rows fully resolved** — label,
   destination, key — and get the user's confirmation before creating the rest.

   Confirmation is not optional here. Each call publishes a live endpoint on the
   public internet and consumes the workspace's plan quota, and a wrong prefix
   across 200 rows is 200 codes to clean up by hand.

## Creating

There is no bulk endpoint. Call the tool once per row, in list order.

- `create_qrcode` — pass `url`, `key`, and `type: "url"`.
- `create_link` — pass `url`, `key`, and `tagIds` when the user wants the batch
  tagged. Create the tag first with `create_tag` and reuse its ID for every row.

A batch does not have to be links. `create_qrcode` also encodes Wi-Fi networks,
contact cards, WhatsApp chats, email, SMS, phone numbers, plain text and crypto
requests — one per room, per branch, per sales rep. Pass `type` and the payload
named after it on every row, exactly as for a single code. The field names have
traps in them, so follow the `wifi-and-contact-qr-codes` skill for the payload
and this one for the batch mechanics.

`create_qrcode` exposes no tag parameter through this connector, so a batch of QR
codes cannot be tagged as it is created. Say that the connector cannot tag them
here — do not say CodeQR cannot tag QR codes, because the dashboard can — and
offer the shared key prefix as the way to group the batch instead.

If a row fails, record the failure and continue with the remaining rows. Report
every failure at the end. Do not stop the batch silently, and do not retry a row
that failed on a plan or quota limit — the retry fails the same way.

## Report back

Return one table, one row per input row:

| label | key | short link | destination | status |

The user pastes this back into their source sheet, so the key and short link
columns matter more than prose. Do not collapse the table into a summary.

## Re-pointing later

When the user returns to change destinations:

1. Find the codes. `list_links` accepts `search`, so filter by the batch prefix
   there. `list_qrcodes` takes only `page` — there is no server-side search, so
   page through the results and match the key prefix yourself.
2. Call `update_qrcode` or `update_link` per code with the new `url`.

Two rules for this step:

- **Never change `key` on a re-point.** `update_link` accepts a new key, and
  using it rewrites the short link itself and breaks every copy already printed
  or shared — the opposite of what this workflow exists for. Change `url` only.
  (`update_qrcode` cannot change the key at all, which is the safer default.)

- **`update_qrcode` reaches printed copies only for dynamic QR codes.** A static
  QR code encodes the destination directly in its printed pattern: the stored
  record changes, and anything already printed keeps leading to the old
  destination forever. Check before promising the change reached the paper.

## Measuring the batch

`get_analytics` with `event: "scans"` for QR codes and `event: "clicks"` for
short links. Pass `qrcodeId` or `linkId` for one code, or omit both for the whole
workspace. `groupBy` accepts time, country, city, device and browser.

Referenced files: 1

qr-analytics-report4.08 KB

View saved version →

---
name: qr-analytics-report
description: Report how CodeQR QR codes and short links are performing - scan and click counts, trend over time, top cities, devices and referrers, and which codes lead. Triggers on how many scans, how many clicks, which cities, best performing, or any request for a campaign report. Not for creating or editing codes, and not for conversion or revenue reporting.
---

# Scan and click reports

Answer performance questions from recorded CodeQR data through `get_analytics`.
Never estimate, extrapolate, or fill a gap with a plausible number.

## The two parameters that are always required

`get_analytics` requires **both** `event` and `groupBy` on every call. Omitting
either one fails the call.

### `event` — pick by resource type, not by phrasing

| Resource | `event` |
|---|---|
| QR code | `scans` |
| Short link | `clicks` |

This is the trap in this workflow. Asking for `clicks` on a QR code does not
error — it returns a well-formed response with nothing in it, which reads exactly
like a code nobody scanned. If a result comes back empty, check that the event
type matches the resource before reporting zero.

`leads`, `sales` and `composite` also exist, but conversion reporting is out of
scope for this skill.

### `groupBy` — shape of the answer

Valid values: `count`, `timeseries`, `countries`, `cities`, `devices`,
`browsers`, `os`, `referers`, `top_links`, `top_qrcodes`, `top_urls`.

Do not pass `clicks`, `scans` or `views` as a `groupBy`. The upstream API accepts
them and currently answers 500, so they are not offered here.

## Scoping and window

- One QR code: `qrcodeId`. One link: `linkId`. Either can also be reached with
  `domain` plus `key`.
- Omit all of them for the whole workspace.
- `interval` accepts `1h`, `24h`, `7d`, `30d`, `90d`, `ytd`, `1y` and `all`. It
  defaults to `24h`, which is short enough to look like a dead code if the user
  meant "ever" — so pass it explicitly whenever the question implies a window.
- Map the user's words to the closest of those and **say which window you used**.
  "This year" is `ytd`, not `90d`. "Ever" or "in total" is `all`.

### Long windows depend on the plan

The API refuses windows above the workspace's plan limit with a 403. It is not
an empty result and not a permissions error the user can fix by re-authorizing:

| Plan | Longest window | Refused |
|---|---|---|
| free | 30 days | `90d`, `ytd`, `1y`, `all` |
| starter | 90 days | `ytd`, `1y`, `all` |
| pro | 1 year | `all` |
| business and above | no limit | — |

`get_workspace` returns the plan. Call it once before a report that needs a long
window, rather than discovering the limit through a rejection.

When the plan blocks the window the user asked for, report the longest one
available, say which plan limit applied, and let them decide — do not silently
substitute a shorter window and present the number as the answer to what they
asked.

## Build the report in this order

1. **Headline** — `groupBy: "count"` for the total over the window.
2. **Trend** — `groupBy: "timeseries"` only when the user asks how it is moving,
   or when the answer is about growth or decline.
3. **One or two breakdowns** — `cities` or `countries` for where, `devices` or
   `os` for how, `referers` for where the traffic came from.
4. **Ranking across codes** — `top_qrcodes` for scans, `top_links` for clicks.

Each of these is a separate call. Run only the ones the question needs: four
breakdowns nobody asked for buries the answer instead of supporting it.

## Reporting rules

- Lead with the number the user asked for, then the context.
- Always state the window and the scope alongside the number. "1,240 scans" on
  its own is not an answer; "1,240 scans in the last 30 days, for the menu QR
  code" is.
- If a query returns empty, report it as no recorded data for that window and
  scope. Do not present it as zero performance without checking the `event` type
  first, and never substitute a made-up figure.
- Scans and clicks are recorded per code with time, country, city and device.
  Personal identity is not part of this data, so do not describe results as
  individual people.

Referenced files: 1

repoint-printed-code3.07 KB

View saved version →

---
name: repoint-printed-code
description: Change where an already printed, posted, or distributed CodeQR code leads, without reprinting or resending anything. Triggers when a destination moved, a landing page changed, a campaign was redirected, or the user asks to fix a QR code or short link that is already out in the world. Not for creating a new code, not for bulk creation across a list, and not for deleting a code.
---

# Re-point a code that is already out in the world

The user has a QR code on paper, or a short link already sent, and the
destination behind it needs to change. The code itself stays exactly as it is.

Work only through the CodeQR MCP tools. Do not generate a replacement QR image:
producing a new image is the failure this workflow exists to avoid.

## 1. Find the code

- **Short links** — `list_links` accepts `search`, `domain` and `tagId`. Search
  by the slug or by words from the destination.
- **QR codes** — `list_qrcodes` accepts only `page`. There is no server-side
  search, so page through the results and match on key or current destination
  yourself. Do not claim a code does not exist until you have reached the last
  page.

Show the user the candidate you found — key, current destination, scan or click
count — and confirm it is the right one before changing anything.

## 2. Check whether the QR code is static before promising anything

Every QR code record carries a `static` boolean. Read it.

- **`static: false` (dynamic)** — the printed pattern encodes a short link, so
  changing the destination re-points every copy already printed. This is the
  case the user is hoping for.

- **`static: true`** — the printed pattern encodes the destination itself.
  Updating the record changes the dashboard entry and nothing else: every sheet,
  label and sign already printed keeps leading to the old destination, forever.

If the code is static, say so **before** making the change, in plain terms: the
record can be updated, but the printed copies cannot be redirected and the only
fix is a new code on new material. Do not report a static update as a success —
that is the one outcome that would leave the user believing a problem is solved
when it is not.

## 3. Make the change

- `update_qrcode` — pass `qrcodeId` and the new `url`.
- `update_link` — pass `linkId` and the new `url`.

**Change `url` only.** `update_link` also accepts `key`, and changing it rewrites
the short link itself, so every copy already printed or sent stops working. Never
change `key` while re-pointing. (`update_qrcode` cannot change the key at all.)

Both tools are annotated as destructive, so the client will ask the user to
confirm. That prompt is correct and expected — let it happen and do not look for
a way around it.

## 4. Confirm the result

Report back three things, explicitly:

- the key and short link, unchanged
- the old destination and the new one
- for a QR code, whether printed copies now follow the change (dynamic) or do
  not (static)

Scan and click history stays attached to the code across a re-point, so the
user's existing numbers are not reset. Say so if they ask.

Referenced files: 1

wifi-and-contact-qr-codes4.71 KB

View saved version →

---
name: wifi-and-contact-qr-codes
description: Create a CodeQR QR code that encodes something other than a web address - Wi-Fi credentials a scan joins, a contact card a scan saves, a WhatsApp chat, an email, an SMS, a phone number, plain text, or a crypto payment request. Triggers on QR code for my wifi, QR with my contact details, vCard QR, WhatsApp QR, or any QR request where the target is not a link. Not for a QR code that opens a URL, not for bulk creation across a list, and not for reading or decoding an existing QR image.
---

# QR codes that encode something other than a link

A CodeQR QR code can carry a Wi-Fi network, a contact card, or a message, not
only a web address. Create these with `create_qrcode` through the CodeQR MCP
tools. Never generate a QR image locally: a local image cannot be edited or
measured afterwards, which is the whole point of creating it here.

## Always send both `type` and the payload of the same name

`type` names what the code encodes. The payload field carries the content, and
it is **named exactly like the type** — `type: "wifi"` goes with a `wifi` object.

`type` defaults to `"url"` when omitted. Sending a `wifi` payload and forgetting
`type` therefore produces a link code with nothing to link to, which saves
without complaint. Pass both, every time.

| `type` | payload | minimum |
|---|---|---|
| `wifi` | `wifi` object | `ssid` |
| `vcard` | `vcard` object | — |
| `whatsapp` | `whatsapp` object | `number` |
| `email` | `email` object | `email` |
| `sms` | `sms` object | `tel` |
| `phone` | `phone` string | the number |
| `text` | `text` string | the text |
| `crypto` | `crypto` object | `address` |

`whatsapp.number` must be E.164 **without** the `+` and without separators —
`5511999999999`, not `+55 11 99999-9999`. The API rejects anything else, so
normalise whatever the user pasted before calling.

## Four field names that are not what you would guess

Payloads are stored as free-form JSON. A misspelled key **saves successfully**
and encodes nothing — there is no error to notice, and the failure only surfaces
when someone scans the printed code. These four are worth reading twice:

- **`email.cco`** is BCC. Not `bcc`. The name is Portuguese, from *com cópia
  oculta*.
- **`sms.subject`** is the **message body**. SMS has no subject line; the field
  is misnamed, not misused.
- **`crypto.address`** is the wallet address. There is a `crypto.email` field in
  the codebase and it is not this one.
- **`vcard`** only encodes `city`, `state`, `zipcode` and `country` when
  `address` is also present — they are assembled into a single address line.
  A city sent on its own is silently dropped.

For an open Wi-Fi network, set `wifi.encryption` to `"nopass"`. Leaving it out,
or inventing a value, produces a code that scanners cannot interpret. Valid
values are `WPA`, `WPA2`, `WEP` and `nopass`. There is no hidden-network option.

## Three types this connector cannot create

`pix`, `geo` and `facetime` exist in the CodeQR dashboard but are not offered
here, because a dynamic one does not currently work: a Pix scan lands on the
site root instead of a payment, a geo code encodes an undefined coordinate, and
FaceTime encodes an empty string.

If the user asks for one, say it is not available through this connector rather
than substituting a different type that looks similar. A Pix payment encoded as
`text` is not a Pix code, and the user finds out at the till.

## Every code created here is dynamic

The printed pattern encodes a short link. A scan resolves it and lands on a
CodeQR page that renders the content — the Wi-Fi join prompt, the contact card,
the payment request. Three consequences worth stating to the user:

1. **The content can be corrected after printing.** A wrong Wi-Fi password is
   fixed with `update_qrcode`; the printed code stays valid.
2. **The type cannot be changed afterwards.** Sending a `wifi` payload to a code
   created as `vcard` returns 200 and changes nothing. To switch, create a new
   code — and say so plainly, because the successful-looking response is exactly
   what would otherwise be reported back as done.
3. **The content is readable by anyone holding the short link.** It is served
   from a public page, so a Wi-Fi password in a QR code is as private as the
   link is unshared. Mention this once for Wi-Fi and crypto codes; do not repeat
   it for a vCard the user is handing out on purpose.

## Report back

Give the short link, and one line describing what a scan does — "joins the
network `Cafe-Guest`", "offers to save Marina Alves as a contact". The user
cannot verify a payload by looking at a QR image, so the sentence is the only
check they have before it goes to print.

Scans are counted the same as any other code: `get_analytics` with
`event: "scans"`.

Referenced files: 1

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package author
CodeQR

Package observed Oct 2, 2026.

Technical details
First seen
Sep 30, 2026 · 22:02 UTC
Last seen
Oct 2, 2026 · 12:00 UTC
Collection status
Collected

plugin_asdk_app_6a76984525848191901ac2d21834803e

Download plugin data (JSON)