Aller au contenu

Suivi des scans & analyses

Aperçu

Chaque scan d’un code QR dynamique génère un enregistrement de scan (Scan-Record) dans votre espace de travail. La collecte s’effectue entièrement à l’Edge Cloudflare — sans services de suivi externes, sans cookies, et sans que l’adresse IP d’origine n’atteigne jamais votre base de données.

Trois façons de consommer les données de scan :

API d'agrégation

GET /v1/codes/:id/scans — Séries temporelles + Top pays/appareils/OS pour un seul objet de code.

Webhooks (temps réel)

Événement qr.scanned par scan, signé avec HMAC-SHA256. Voir Webhooks.

Tableau de bord

Visualisation dans le tableau de bord qr3.app — aucun appel API requis.


Quelles données sont collectées

Pour chaque scan, un enregistrement est créé dans la table scans :

ChampSourceExemple
idUUID généré par le serveurscn_d1f8…
code_idID du code QR scannéqr_a1b2c3d4
workspace_idEspace de travail du codews_xxx
countryCloudflare cf.countryAT
regionCloudflare cf.regionVienna
cityCloudflare cf.cityWien
device_typeAnalyse du User-Agentmobile, tablet, desktop
osAnalyse du User-AgentiOS, Android, macOS, Windows
browserAnalyse du User-AgentSafari, Chrome, Firefox
refererEn-tête HTTP Refererhttps://example.com/landing
languageEn-tête Accept-Language (première langue)de
redirected_toDestination réelle de la redirectionhttps://example.com
ip_hashSHA-256(IP + sel quotidien) — non réversible8f3a…
scanned_atHorodatage ISO-86012026-05-12T14:32:11.000Z

Géolocalisation à l’Edge

Toutes les données géographiques (country, region, city) proviennent de l’objet cf de Cloudflare et sont basées sur la base de données Geo-IP de Cloudflare. Aucun service Geo-IP externe n’est interrogé — la résolution s’effectue dans le même Worker qui exécute la redirection.

Cela a trois conséquences :

  1. Faible latence — pas de saut supplémentaire, pas de résolution DNS vers un fournisseur externe.
  2. Protection des données — l’adresse IP ne quitte pas Cloudflare et n’est jamais transmise à des tiers.
  3. Granularité limitée — la ville (city) n’est pas toujours disponible (par exemple avec les VPN, les opérateurs mobiles ou les petites régions). Attendez-vous à des valeurs null et prévoyez-les dans vos tableaux de bord.

Consulter les analyses de scan

GET /v1/codes/:id/scans

Fournit des analyses agrégées pour un seul code QR sur une période sélectionnable.

Fenêtre de terminal
curl "https://qr3.app/v1/codes/qr_a1b2c3d4/scans?days=30" \
-H "Authorization: Bearer qr3_sk_..."

Paramètres de requête :

ParamètreTypePar défautDescription
daysinteger30Période en jours (1–365)

Réponse (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" }
}

Champs de réponse :

ChampDescription
total_scansNombre total de scans cumulés du code (indépendamment de la période days)
period_scansSomme des scans dans la période sélectionnée
scans_by_dayGroupements par jour, par ordre chronologique, les jours vides sont omis
top_countriesTop 8 des pays sur la période, par ordre décroissant
top_devicesTop 5 des types d’appareils (mobile, tablet, desktop)
top_osTop 5 des systèmes d’exploitation

Agrégation sur plusieurs codes

Les totaux à l’échelle de l’espace de travail (par exemple, les scans par mois sur tous les codes) sont disponibles via GET /v1/workspaces/:id dans le champ scans_this_month. Pour les analyses multi-codes, nous recommandons le tableau de bord ou un export périodique.


Consommation en temps réel via Webhooks

Si vous souhaitez traiter les événements de scan dès qu’ils se produisent — par exemple pour des tableaux de bord en direct, le suivi des leads ou des intégrations CRM — abonnez-vous à l’événement qr.scanned :

Fenêtre de terminal
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"
}
}

Documentation complète sur la vérification des signatures, la logique de tentative et les journaux de livraison dans API → Webhooks.


RGPD & Protection des données

Les enregistrements de scan ne contiennent aucune adresse IP personnelle. L’IP d’origine est remplacée dans le Worker Edge par une fonction de hachage cryptographique (SHA-256) avec un sel rotatif quotidien (salt). Cela signifie :

  • Pas de ré-identification possible, même en connaissant l’algorithme
  • Pas de corrélation d’un jour à l’autre pour un même visiteur
  • L’IP d’origine n’atteint jamais la base de données D1

La rétention dépend de l’abonnement :

AbonnementRétention
Free7 jours
Pro90 jours
Business / Agency1 an
EnterprisePersonnalisé (SLA)

Une tâche cron quotidienne (purgeOldScans) supprime automatiquement les enregistrements plus anciens — le champ total_scans de l’objet de code n’est pas affecté.


Bonnes pratiques

  • Fréquence d’interrogation (Polling) : L’API d’agrégation est performante, mais n’est pas conçue pour une interrogation à la seconde. Pour les mises à jour en temps réel, privilégiez toujours les webhooks et n’utilisez l’API que pour les rattrapages (backfills) ou les tableaux de bord.
  • Mise en cache : La réponse contient des séries temporelles — pour de larges périodes (days=365), la charge utile (payload) peut atteindre plusieurs Ko. Mettez en cache côté client avec une courte durée de vie (TTL, par exemple 60 s).
  • Limites Top-N : top_countries, top_devices et top_os sont limités côté serveur à respectivement 8 et 5 entrées. Pour des analyses plus approfondies, exportez les données brutes.
  • Tolérer les valeurs null : country, region, city, referer et language peuvent être null. Traisez cela comme « Inconnu » dans vos analyses.