Analytics
GET /v1/analytics renvoie les chiffres que montre la page d'accueil du tableau de bord pour une période : dix KPIs, chacun avec sa valeur sur une période de comparaison et la variation, et huit séries de graphiques. Utilisez-le pour les rapports de vos clients ou un export vers un outil BI, au lieu de recalculer les chiffres depuis GET /v1/orders. L'API et le tableau de bord partagent les mêmes définitions et le même cache : pour une même période, ils affichent les mêmes chiffres. Le sens de chaque chiffre pour le marchand est expliqué sur la page Analytics de la documentation marchand.
L'API compte toujours tout le trafic : pages de la boutique et pages de destination ensemble. Le filtre de trafic du tableau de bord (pages de destination seulement, ou boutique seulement) n'a pas d'équivalent ici.
Avant de commencer
- La clé a besoin de
analytics:read. Les clés créées depuis le tableau de bord (Paramètres → API,/dashboard/api) l'ont depuis la v1.7. Les portées sont figées à la création de la clé : une clé plus ancienne répond403 forbiddenavec « Missing scope: analytics:read ». Créez alors une nouvelle clé depuis le tableau de bord. Une clé créée parPOST /v1/keysn'obtient que les portées que détient la clé qui l'a créée. - Les clés personnelles demandent une boutique avec un plan Enterprise actif. Le jeton d'une app installée n'est pas lié à Enterprise, mais il lui faut
analytics:readparmi les portées que le marchand a acceptées. Voir Introduction. - Le revenu, le profit et le panier moyen, ainsi que les valeurs
revenuedans les graphiques, ne sont envoyés que si la clé appartient au compte du propriétaire de la boutique. Sinon ces champs sont absents de la réponse : ils ne valent ni0ninull.
| Portée | Description |
|---|---|
analytics:read | Lire les statistiques et les KPIs de la boutique. Incluse dans les clés marchand créées à partir de la v1.7 ; une clé plus ancienne demande une nouvelle clé. |
GET /v1/analytics
Le rapport d'une période.
Auth : clé plateforme avec analytics:read.
Paramètres de requête
| Param | Type | Défaut | Notes |
|---|---|---|---|
range | string | this_month | today, yesterday, 7d, 30d, this_month, last_month, this_year ou custom. Toute autre valeur renvoie 400 bad_request. |
from | YYYY-MM-DD | aucun | Premier jour. Obligatoire avec range=custom, ignoré sinon. |
to | YYYY-MM-DD | aucun | Dernier jour. Obligatoire avec range=custom, ignoré sinon. Jamais avant from, au plus 365 jours après. |
Périodes
range | Période | Comparée à | group_by |
|---|---|---|---|
today | Aujourd'hui | Hier | hour |
yesterday | Hier | La veille | hour |
7d | Aujourd'hui et les 6 jours d'avant | Les 7 jours qui précèdent | day |
30d | Aujourd'hui et les 29 jours d'avant | Les 30 jours qui précèdent | day |
this_month | Du 1er au dernier jour du mois en cours | Tout le mois précédent | day |
last_month | Tout le mois précédent | Le mois d'avant | day |
this_year | Du 1er janvier au 31 décembre de l'année en cours | Toute l'année précédente | month |
custom | De from à to, les deux jours compris | Le même nombre de jours juste avant from | hour, day ou month |
Pour custom, group_by vaut hour quand to est from ou le lendemain, day quand to tombe au plus 90 jours après from, et month au-delà. this_month et this_year vont jusqu'à la fin du mois ou de l'année : ils comparent donc les jours écoulés à un mois ou une année précédente entière.
Le rapport est mis en cache 120 secondes par boutique et par période, et le tableau de bord lit le même cache. Un appel peut renvoyer des chiffres vieux de deux minutes au plus, et les appels faits dans cet intervalle obtiennent les mêmes chiffres.
Requête
curl 'https://api.dzbuild.app/v1/analytics?range=7d' \
-H "Authorization: Bearer $DZ_KEY"
Une période personnalisée :
curl 'https://api.dzbuild.app/v1/analytics?range=custom&from=2026-09-01&to=2026-09-30' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
La réponse pour range=7d le 6 octobre 2026, à une clé créée par le propriétaire de la boutique. Les séries temporelles et les listes sont coupées après leurs premiers éléments.
{
"data": {
"period": {
"from": "2026-09-30 00:00:00",
"to": "2026-10-06 23:59:59",
"prev_from": "2026-09-23 00:00:00",
"prev_to": "2026-09-29 23:59:59",
"label": "7d",
"group_by": "day"
},
"kpis": {
"total_orders": { "value": 48, "change": 20, "previous": 40 },
"delivered_orders": { "value": 31, "change": 7, "previous": 29 },
"cancelled_orders": { "value": 6, "change": -25, "previous": 8 },
"total_revenue": { "value": 186000, "change": 8, "previous": 172000 },
"total_profit": { "value": 61500, "change": 6, "previous": 58000 },
"avg_order_value": { "value": 4350, "change": -1, "previous": 4400 },
"total_visitors": { "value": 1520, "change": 17, "previous": 1300 },
"page_views": { "value": 4810, "change": 17, "previous": 4100 },
"conversion_rate": { "value": 3.2, "change": 3, "previous": 3.1 },
"new_customers": { "value": 41, "change": 17, "previous": 35 }
},
"charts": {
"revenue_over_time": [
{ "label": "09/30", "orders": 7, "revenue": 24500 },
{ "label": "10/01", "orders": 5, "revenue": 18000 }
],
"orders_by_hour": [
{ "hour": "00:00", "orders": 0, "impressions": 35 },
{ "hour": "01:00", "orders": 1, "impressions": 22 }
],
"orders_by_status": {
"pending": 5,
"confirmed": 4,
"processing": 2,
"shipped": 9,
"delivered": 20,
"cancelled": 6,
"returned": 2
},
"top_products": [
{
"id": 12,
"name": "Classic watch",
"image": "https://cdn.dzbuild.app/uploads/products/123/123_1700000000_example.webp",
"qty_sold": 14,
"revenue": 49000,
"views": 380
}
],
"visitors_over_time": [
{ "label": "09/30", "page_views": 690, "unique_visitors": 215, "orders": 7 },
{ "label": "10/01", "page_views": 702, "unique_visitors": 230, "orders": 5 }
],
"devices": {
"desktop": { "count": 510, "percent": 11 },
"mobile": { "count": 4180, "percent": 87 },
"tablet": { "count": 120, "percent": 2 }
},
"traffic_sources": [
{ "source": "facebook", "count": 2900, "percent": 60 },
{ "source": "direct", "count": 1210, "percent": 25 },
{ "source": "tiktok", "count": 700, "percent": 15 }
],
"top_wilayas": [
{ "wilaya": "الجزائر", "orders": 9, "revenue": 41000 },
{ "wilaya": "وهران", "orders": 6, "revenue": 27500 }
]
}
}
}
La période
| Champ | Signification |
|---|---|
from, to | Début et fin de la période, YYYY-MM-DD HH:MM:SS, heure d'Alger. |
prev_from, prev_to | Début et fin de la période de comparaison. |
label | Le range demandé. |
group_by | Taille des intervalles de revenue_over_time et visitors_over_time : hour, day ou month. |
KPIs
Chaque KPI porte trois nombres : value pour la période, previous pour la période de comparaison, et change, la variation en pourcentage arrondie à l'entier. Quand previous vaut 0 ou moins, change vaut 100 si value est supérieur à 0, et 0 sinon. Les montants sont arrondis à l'entier.
| KPI | Ce qu'il compte |
|---|---|
total_orders | Commandes créées dans la période, quel que soit leur statut. |
delivered_orders | Commandes livrées dans la période, comptées le jour de leur livraison. |
cancelled_orders | Commandes créées dans la période et désormais annulées. |
total_revenue | Propriétaire uniquement. Sous-total moins remise des commandes livrées dans la période. Livraison et frais de paiement non compris. |
total_profit | Propriétaire uniquement. total_revenue moins quantité × prix de revient des articles de ces commandes. Un produit sans prix de revient compte pour un coût nul. |
avg_order_value | Propriétaire uniquement. Total moyen des commandes créées dans la période, commandes annulées et retournées exclues. |
total_visitors | Visiteurs distincts dans la période, pages de la boutique et pages de destination ensemble. |
page_views | Pages vues dans la période, pages de la boutique et pages de destination ensemble. |
conversion_rate | total_orders ÷ total_visitors × 100, avec une décimale. 0 quand il n'y a eu aucun visiteur. |
new_customers | Fiches clients créées dans la période. |
Ces KPIs viennent d'ensembles de commandes différents, ils ne se recoupent donc pas : total_revenue ÷ total_orders ne donne pas avg_order_value.
Graphiques
| Graphique | Contenu |
|---|---|
revenue_over_time | Un élément par intervalle : label, les orders créées dans l'intervalle et, pour le propriétaire uniquement, revenue, la somme des totaux de celles qui sont désormais livrées. Ce n'est pas total_revenue, qui compte au jour de livraison et laisse de côté les frais de livraison. |
orders_by_hour | Toujours 24 éléments, de 00:00 à 23:00 : les commandes créées et les pages vues (impressions) à cette heure de la journée, sur toute la période. |
orders_by_status | Commandes créées dans la période par statut actuel : pending, confirmed, processing, shipped, delivered, cancelled et returned. |
top_products | Jusqu'à 10 produits par quantité vendue dans les commandes créées dans la période, commandes annulées et retournées exclues. Chacun a id, name, image (URL de l'image principale ou null), qty_sold, views (visiteurs distincts sur le produit dans la période) et, pour le propriétaire uniquement, revenue (quantité × prix inscrit sur la commande). |
visitors_over_time | Un élément par intervalle : label, page_views, unique_visitors et orders. Un visiteur qui revient un autre jour compte dans les deux intervalles, donc la somme des unique_visitors peut dépasser total_visitors. |
devices | Pages vues par appareil : clés desktop, mobile et tablet, chacune avec count et percent. Un appareil sans vue n'a pas de clé, et le champ est un tableau vide [] quand la période n'a eu aucune visite. |
traffic_sources | Jusqu'à 6 sources par pages vues, la plus forte en premier, chacune avec source, count et percent. percent est la part parmi les sources listées. |
top_wilayas | Jusqu'à 10 wilayas par nombre de commandes créées dans la période, tous statuts : wilaya (le nom en arabe, غير محدد pour les commandes sans wilaya), orders et, pour le propriétaire uniquement, revenue, la somme des totaux de ces commandes quel que soit leur statut. |
Les libellés suivent group_by : 00:00 à 23:00 pour hour (24 éléments ; une période custom de deux jours additionne les deux jours dans les mêmes heures), MM/DD pour day, et le mois en anglais avec l'année pour month, par exemple Sep 2026. Les jours après aujourd'hui et les mois après le mois en cours sont omis.
La plateforme enregistre source parmi direct, facebook, instagram, tiktok, google, youtube, twitter, snapchat, telegram ou other. Une visite dont le lien porte utm_source est classée selon ce tag (fb compte comme facebook, ig comme instagram, x comme twitter, tout tag hors de la liste comme other) ; une visite sans lui est classée selon le site d'où elle vient.
Erreurs
| HTTP | Code | Cause |
|---|---|---|
| 400 | bad_request | range n'est pas l'une des huit valeurs (« Invalid range. Allowed: ... »), ou une période custom dont from ou to manque ou n'est pas au format YYYY-MM-DD, ou dont to est avant from ou plus de 365 jours après (« Invalid date range ... »). |
| 401 | unauthorized | Clé invalide ou manquante. |
| 402 | quota_exceeded | Le quota mensuel de requêtes de la boutique est épuisé. Voir Limites de taux. |
| 403 | forbidden | « Missing scope: analytics:read », ou une clé personnelle dont la boutique n'a pas de plan Enterprise actif (« API access requires an active Enterprise plan »). |
| 429 | rate_limited | Plafond par minute de la boutique, partagé par toutes ses clés, ou plafond propre à chaque installation pour le jeton d'application installée. Attendez la durée de Retry-After. Voir Limites de taux. |
Limites connues
- Fins de mois. Quand le numéro du jour n'existe pas dans le mois précédent, comme le 31 octobre,
range=last_monthrenvoie le mois en cours etrange=this_monthest comparé au mois en cours lui-même.last_monthest aussi comparé à lui-même quand le jour n'existe pas deux mois plus tôt, comme le 30 avril. Ces jours-là, demandez les dates voulues avecrange=custom.