Gå til indhold

Scan-tracking & Analytics

Oversigt

Hvert scan af en dynamisk QR-kode opretter en scan-record i dit workspace. Indsamlingen sker fuldstændigt på Cloudflare-edge — uden eksterne trackingtjenester, uden cookies, og uden at den originale IP-adresse nogensinde når din database.

Tre måder at forbruge scandata på:

Aggregerings-API

GET /v1/codes/:id/scans — tidsserier + top-lande/-enheder/-OS for et enkelt kodeobjekt.

Webhooks (realtid)

qr.scanned-event pr. scan, HMAC-SHA256-signeret. Se Webhooks.

Dashboard

Visualisering i qr3.app-dashboardet — intet API-kald nødvendigt.


Hvilke data indsamles

For hvert scan oprettes der en record i tabellen scans:

FeltKildeEksempel
idServergenereret UUIDscn_d1f8…
code_idKode-ID for den scannede QR-kodeqr_a1b2c3d4
workspace_idKodens workspacews_xxx
countryCloudflare cf.countryAT
regionCloudflare cf.regionVienna
cityCloudflare cf.cityWien
device_typeUser-Agent-parsingmobile, tablet, desktop
osUser-Agent-parsingiOS, Android, macOS, Windows
browserUser-Agent-parsingSafari, Chrome, Firefox
refererHTTP Referer-headerhttps://example.com/landing
languageAccept-Language-header (første sprog)de
redirected_toFaktisk redirect-destinationhttps://example.com
ip_hashSHA-256(IP + daglig salt) — ikke-reversibel8f3a…
scanned_atISO-8601-tidsstempel2026-05-12T14:32:11.000Z

Geolokalisering på edge

Alle geodata (country, region, city) stammer fra Cloudflares cf-objekt og er baseret på Cloudflares Geo-IP-database. Der anmodes ikke om eksterne Geo-IP-tjenester — opløsningen sker i den samme worker, som også udfører redirectet.

Dette har tre konsekvenser:

  1. Lav latenstid — intet ekstra hop, intet DNS-opslag hos en ekstern udbyder.
  2. Databeskyttelse — IP-adressen forlader ikke Cloudflare og videregives aldrig til tredjeparter.
  3. Begrænset granularitetcity er ikke altid tilgængelig (f.eks. ved VPN’er, mobiludbydere eller små regioner). Forvent null-værdier og tag højde for dem i dine dashboards.

Forespørg scan-analytics

GET /v1/codes/:id/scans

Leverer aggregeret analytics for en enkelt QR-kode over en valgt tidsperiode.

Terminal window
curl "https://qr3.app/v1/codes/qr_a1b2c3d4/scans?days=30" \
-H "Authorization: Bearer qr3_sk_..."

Query-parametre:

ParameterTypeStandardBeskrivelse
daysinteger30Tidsperiode i dage (1–365)

Response (HTTP 200):

{
"data": {
"code_id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"total_scans": 1842,
"period_days": 30,
"period_scans": 367,
"scans_by_day": [
{ "date": "2026-04-13", "count": 12 },
{ "date": "2026-04-14", "count": 18 }
],
"top_countries": [
{ "value": "AT", "count": 142 },
{ "value": "DE", "count": 98 },
{ "value": "CH", "count": 41 }
],
"top_devices": [
{ "value": "mobile", "count": 281 },
{ "value": "desktop", "count": 72 },
{ "value": "tablet", "count": 14 }
],
"top_os": [
{ "value": "iOS", "count": 158 },
{ "value": "Android", "count": 123 },
{ "value": "macOS", "count": 48 }
]
},
"meta": { "request_id": "req_xyz123" }
}

Svarfelter:

FeltBeskrivelse
total_scansSamlet antal scan i kodens levetid (uafhængigt af days-vinduet)
period_scansSummen af scan i det valgte tidsvindue
scans_by_dayDaglige buckets, stigende efter dato, tomme dage udelades
top_countriesTop 8 lande i tidsvinduet, faldende
top_devicesTop 5 enhedstyper (mobile, tablet, desktop)
top_osTop 5 operativsystemer

Aggregering på tværs af flere koder

Workspace-dækkende summe (f.eks. scan pr. måned på tværs af alle koder) er tilgængelige via GET /v1/workspaces/:id i feltet scans_this_month. Til analyser på tværs af koder anbefaler vi dashboardet eller en periodisk eksport.


Realtidsforbrug via webhooks

Hvis du vil behandle scan-events, så snart de sker — f.eks. til live-dashboards, lead-tracking oder CRM-integrationer — skal du abonnere på qr.scanned-eventet:

Terminal window
curl -X POST https://qr3.app/v1/webhooks \
-H "Authorization: Bearer qr3_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/qr3",
"events": ["qr.scanned"],
"secret": "my-secret-key-min-16-chars"
}'

Payload:

{
"id": "evt_abc123xyz",
"type": "qr.scanned",
"created": "2026-05-12T14:32:11.000Z",
"data": {
"code_id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"scan_id": "scn_d1f8...",
"country": "AT",
"device_type": "mobile",
"os": "iOS"
}
}

Komplet dokumentation om signaturverifikation, retry-logik og leveringslogge findes i API → Webhooks.


GDPR & databeskyttelse

Scan-records indeholder ingen personhenførbare IP-adresser. Den oprindelige IP-adresse erstattes i edge-workeren af en kryptografisk hashfunktion (SHA-256) med en dagligt roterende salt. Det betyder:

  • Ingen re-identifikation, selv hvis algoritmen er kendt
  • Ingen korrelation af den samme besøgende på tværs af dage
  • Den originale IP-adresse når aldrig D1-databasen

Opbevaringstid afhænger af din plan:

PlanOpbevaringstid
Free7 dage
Pro90 dage
Business / Agency1 år
EnterpriseCustom (SLA)

Et dagligt cronjob (purgeOldScans) fjerner automatisk ældre records — total_scans på kodeobjektet forbliver upåvirket af dette.


Best practices

  • Polling-frekvens: Aggregerings-API’en er billig, men er ikke beregnet til at blive kaldt hvert sekund. Foretræk altid webhooks til live-opdateringer, og brug kun API’en til backfills / dashboards.
  • Caching: Svaret indeholder tidsserier — ved store tidsvinduer (days=365) kan payloaden blive flere KB stor. Cache på klientsiden med en kort TTL (f.eks. 60 s).
  • Top-N-grænser: top_countries, top_devices og top_os er begrænset på serversiden til henholdsvis 8 og 5 poster. Eksporter rådataene for mere dybdegående analyser.
  • Tolerer null-værdier: country, region, city, referer og language kan være null. Håndter dette som “Ukendt” i din analyse.