qr-code-scanner-tracking
Provided by TippyEntertainment
https://github.com/tippyentertainment/skills.git
This skill is designed for use on the Tasking.tech agent platform (https://tasking.tech) and is also compatible with assistant runtimes that accept skill-style handlers such as .claude, .openai, and .mistral. Use this skill for both Claude code and Tasking.tech agent source.
qr-code-scanner-tracking
Summary
Design, build, and refine a QR code–based tracking system. This skill helps generate QR codes, define what happens when they are scanned, and track scan events (who, where, when, how) for marketing, operations, product flows, or internal tools.
When to Use
Use this skill when the user wants to:
- Create QR codes that point to dynamic tracking URLs.
- Track scans and conversions from flyers, packaging, events, screens, or internal assets.
- Run campaign‑level or per‑user/per‑asset tracking via QR codes.
- Implement a scan → route → log flow (scan opens a page, triggers analytics, and records metadata).
- Integrate QR scanning into web or mobile apps (e.g., internal apps, kiosks, field tools).
This skill focuses on architecture, data modeling, and code scaffolding around QR generation and scan tracking.
Inputs to Collect
The assistant should ask for:
Business Context
- Primary use case
- Examples: marketing campaign tracking, event check‑ins, product packaging, asset tracking, login/device pairing, in‑store signage.
- What should happen on scan
- Redirect to a landing page, open an app deep link, show a dynamic screen, start a flow (e.g., sign‑up).
- Tracking goals
- Need to measure: total scans, unique scanners, location, conversion to sign‑up/purchase, per‑channel performance, etc.
Technical Context
- Existing stack
- Frontend: React, Next.js, Vue, Svelte, SPA, native apps.
- Backend: Node, Deno, Python, Cloudflare Workers, AWS Lambda, etc.
- Hosting / platform
- Cloudflare (Workers/Pages/D1), AWS, GCP, on‑prem, etc.
- Expected scale
- Approximate number of QR codes and expected scans per day.
Data & Privacy
- Data to capture per scan
- At minimum: timestamp, QR code ID, campaign/channel.
- Optional: IP/geo (anonymized), device type, user ID/session ID, referrer.
- Privacy / compliance
- Requirements for consent, anonymization, and data retention.
If key details are missing, ask 2–4 clarifying questions before proposing a solution.
Expected Behavior
1. Clarify Requirements
- Summarize the use case in a few bullets (e.g., “Track scans from conference badges and attribute sign‑ups to specific booths/QRs”).
- Identify:
- Tracking granularity (per campaign, per medium, per asset, per person).
- Any constraints around offline usage or printing.
2. Propose Architecture
Break the system into clear components:
QR Code Generation Service
- Responsibilities:
- Create QR codes with unique tokens/IDs.
- Associate each token with:
- Destination URL or app deep link.
- Campaign/channel metadata (e.g.,
utm_source,utm_medium). - Optional per‑asset or per‑user labels.
- Design:
- A backend API or CLI to generate and store QR definitions.
- Optional admin UI for non‑technical users to create/manage codes.
- Options:
- Support static destination URLs or dynamic rules (e.g., A/B tests, geo‑dependent destinations).
Scan Handler / Redirect Endpoint
- Route pattern:
- e.g.
https://app.example.com/q/{token}or custom domain/r/{token}.
- e.g.
- Responsibilities:
- Parse token from the URL.
- Look up QR definition in the database.
- Log a scan event with metadata.
- Redirect to the destination URL (or render a dynamic page).
- Behavior for errors:
- Invalid/unknown token → show friendly error page.
- Inactive/expired codes → show fallback/expired message.
Tracking & Storage
-
Data model (example):
-
qr_codesidtoken(unique)campaign_id(optional)destination_urllabel(human‑readable name)metadata_json(optional)is_active(boolean)created_atexpires_at(optional)
-
qr_scan_eventsidqr_code_idscanned_atip_hashorip_truncated(optional, privacy‑aware)user_agentreferrergeo_region(optional, if platform provides coarse region)user_idorsession_id(optional)meta_json(extra context: channel, device, app info)
-
-
Storage options:
- Lightweight DB (Cloudflare D1, DynamoDB, Postgres, etc.).
- Optional export to analytics warehouse (BigQuery/Redshift/ClickHouse) if needed.
Analytics & Reporting
- Queries and metrics:
- Scans per campaign, per day, per channel.
- Top performing codes.
- Conversion metrics when tied to downstream events (e.g., sign‑ups).
- Dashboard ideas:
- Time‑series charts.
- Table of campaigns and scan counts.
- Device/browser breakdown.
- Map of approximate regions (if geo tracked).
Scanner Integration (Optional)
- Browser‑based scanner:
- Use
getUserMedia+ JavaScript QR decoder for internal tools or kiosks.
- Use
- Native app integration:
- Use platform scanners and direct results to the same
/q/{token}endpoints or custom deep links.
- Use platform scanners and direct results to the same
- Decide:
- Whether scanner is only internal, or exposed to end‑users through apps.
3. Generate Implementation Scaffolding
The skill should produce implementation‑ready scaffolding appropriate to the user’s stack. Examples:
Example Scan Handler (TypeScript / Cloudflare Worker Style)
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const segments = url.pathname.split('/').filter(Boolean);
const token = segments[segments.length - 1]; // /q/{token}
if (!token) {
return new Response('Invalid QR code', { status: 400 });
}
// Look up QR code
const qr = await env.DB.prepare(
'SELECT id, destination_url, campaign_id, is_active FROM qr_codes WHERE token = ?'
).bind(token).first();
if (!qr || !qr.is_active) {
return new Response('QR code not found or inactive', { status: 404 });
}
// Collect metadata
const ua = request.headers.get('user-agent') ?? '';
const ip = request.headers.get('cf-connecting-ip') ?? '';
const now = new Date().toISOString();
// Persist scan event (with hashed/truncated IP if required)
await env.DB.prepare(
'INSERT INTO qr_scan_events (qr_code_id, scanned_at, user_agent, ip_hash) VALUES (?, ?, ?, ?)'
).bind(qr.id, now, ua, hashIp(ip)).run();
// Redirect to destination URL
return Response.redirect(qr.destination_url, 302);
},
};