# DataFirefly Push Pro — Guide complet

> DataFirefly Push Pro apporte les notifications push web natives à PrestaShop 8 et 9 sans aucun service tiers de type OneSignal ni abonnement mensuel. Ce guide couvre l'installation, la configuration…

- Page: <https://www.datafirefly.com/documentation/dfpushnotifications/>
- Langue: fr
- Mis à jour le: 2026-06-28
- Autres langues: [en](https://www.datafirefly.com/en/documentation/dfpushnotifications/index.md), [es](https://www.datafirefly.com/es/documentation/dfpushnotifications/index.md), [de](https://www.datafirefly.com/de/documentation/dfpushnotifications/index.md), [it](https://www.datafirefly.com/it/documentation/dfpushnotifications/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfpushnotifications/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfpushnotifications/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfpushnotifications/index.md)
- Index: <https://www.datafirefly.com/documentation/llms.txt>

DataFirefly Push Pro apporte les notifications push web natives à PrestaShop 8 et 9 sans aucun service tiers de type OneSignal ni abonnement mensuel. Ce guide couvre l'installation, la configuration initiale, les neuf automatisations, le builder de campagnes, la segmentation, l'A/B testing, l'attribution du chiffre d'affaires, les topics, l'inbox, les webhooks et le dépannage.

## 1. Présentation et cas d'usage

Le module implémente nativement le protocole Web Push VAPID (RFC 8292) avec chiffrement aes128gcm côté serveur. Les abonnements sont stockés dans votre base PrestaShop, les envois partent directement de votre hébergement, aucune donnée ne transite par un service tiers.

Cas d'usage typiques :

- **Récupération de paniers abandonnés** : trois relances espacées (1 h, 24 h, 72 h) sans dépendre de l'e-mail du visiteur.
- **Alertes produit** : retour en stock, baisse de prix, opt-in directement sur la fiche produit.
- **Transactionnel** : confirmation de commande, expédition, demande d'avis après livraison.
- **Réengagement** : anniversaire, clients inactifs, digest des nouveaux produits.
- **Campagnes ponctuelles** : soldes, lancements, Black Friday, avec segmentation et A/B testing.

## 2. Pré-requis

- PrestaShop 8.0 à 9.x
- PHP 7.4 minimum, 8.x recommandé
- MySQL 5.7 minimum ou MariaDB 10.3
- **HTTPS obligatoire** : l'API Web Push des navigateurs ne fonctionne que sur une origine sécurisée. Seul `localhost` fait exception pour les tests en développement.
- Un cron externe capable d'appeler une URL HTTP toutes les 5 minutes (cron Linux, tâches planifiées de l'hébergeur, cron PrestaShop natif, etc.)
- OpenSSL activé en PHP (utilisé pour la génération des clés VAPID et le chiffrement aes128gcm)

**Pourquoi HTTPS ?** Tous les navigateurs (Chrome, Firefox, Safari, Edge) refusent d'enregistrer un service worker ou d'accorder la permission notifications sur une page HTTP. C'est une limitation des navigateurs, pas du module.

## 3. Installation

1. Téléchargez le ZIP `dfpushnotifications-v1.2.0-phase3.zip` depuis votre espace client DataFirefly.
2. Back-office PrestaShop → Modules → Gestionnaire de modules → **Téléverser un module** → sélectionnez le ZIP.
3. Cliquez sur **Installer**. L'installation crée 14 tables sous le préfixe `ps_dfpush_*`, génère un token cron unique et enregistre les onglets BO.
4. Un nouveau menu apparaît : **Améliorer → DataFirefly Push** avec 8 onglets (Dashboard, Campaigns, Automations, Queue, Subscribers, Topics, Webhooks, Settings).

## 4. Génération des clés VAPID

Les clés VAPID identifient votre serveur auprès des push services des navigateurs (FCM, Mozilla autopush, Apple push). Elles sont générées une seule fois et ne doivent jamais changer après mise en production (sinon tous les abonnés deviennent injoignables).

1. Allez dans **DataFirefly Push → Opt-in & Settings**.
2. Cliquez sur **Generate VAPID keys**. Le module crée une paire de clés ECDSA P-256 stockée dans la configuration PrestaShop.
3. Saisissez un **VAPID subject** : une URL `mailto:` avec votre adresse de contact technique (ex. `mailto:admin@votreshop.com`). C'est l'identifiant que les push services peuvent contacter en cas d'abus.
4. Activez le module via le toggle **Push notifications enabled**.

**Sauvegardez vos clés.** Si vous régénérez les clés VAPID après le lancement, tous vos abonnés existants seront rejetés par les push services avec un code 410 Gone. Conservez une sauvegarde de la base PrestaShop avant toute manipulation des clés.

## 5. Configuration de l'opt-in

L'onglet **Opt-in & Settings** contrôle l'affichage de la demande de permission. Trois styles sont disponibles :

- **Bell** : une cloche flottante en bas à droite. L'utilisateur clique, puis le navigateur affiche sa demande native. Le moins intrusif.
- **Banner** : une bannière persistante en haut ou en bas de page avec deux boutons (autoriser / refuser).
- **Modal** : une fenêtre modale centrée, plus visible mais aussi plus agressive.

### Déclencheurs

Pour ne pas afficher la demande dès la première seconde (taux de refus élevé), choisissez un déclencheur :

- **Delay** : afficher après X secondes (par défaut 15 s)
- **Scroll** : afficher après X % de scroll de la page (par défaut 40 %)
- **Pages** : afficher après X pages vues dans la session (par défaut 2)

### Cooldown

Si le visiteur ferme ou refuse la demande, un cooldown empêche de la lui repropose pendant N jours (par défaut 7). Ça évite l'effet "popup harceleur" qui pousse les utilisateurs à bloquer définitivement le domaine.

### Plafond journalier et heures de silence

- **Max per day** : nombre maximum de notifications envoyées à un même abonné par jour (par défaut 3). Au-delà, la file d'envoi rejette silencieusement les messages excédentaires.
- **Quiet hours** : plage horaire pendant laquelle aucune notification n'est délivrée. Les messages enfilés pendant cette plage sont reprogrammés au matin de la première fenêtre non-silencieuse.

## 6. Cron : configuration et token

Le cron pilote toutes les opérations différées : automatisations, file d'envoi, drainage des webhooks, nettoyage. Il doit être appelé toutes les 5 minutes via une URL HTTP sécurisée par token.

### Token

Un token unique est généré à l'installation. Pour le récupérer : **DataFirefly Push → Automations**, le bandeau bleu en haut affiche l'URL complète à copier-coller dans votre cron.

### Exemple de cron Linux

```
*/5 * * * * curl -s "https://votreshop.com/module/dfpushnotifications/cron?token=VOTRE_TOKEN" > /dev/null
```

### Tâches exécutées à chaque tick

1. Réinitialisation des compteurs journaliers (une fois par jour, au franchissement de minuit)
2. Exécution des automatisations à délai mature (paniers abandonnés 1 h / 24 h / 72 h, anniversaire, inactivité, nouveaux produits, demandes d'avis programmées)
3. Déclenchement des campagnes programmées dont la date est arrivée
4. Drainage de la file d'envoi (jusqu'à 50 notifications par batch par défaut, configurable)
5. Drainage de la file des webhooks (jusqu'à 100 par batch)
6. Nettoyage des entrées anciennes (sent > 60 jours, webhook log > 30 jours)

La réponse du cron est un JSON détaillant chaque étape :

```
{
  "success": true,
  "tasks": {
    "reset_counters": "ok",
    "triggers": { "abandoned_1h": 12, "abandoned_24h": 4, "birthday": 2, "inactivity": 38 },
    "scheduled_campaigns": 1,
    "queue": { "processed": 50, "sent": 47, "failed": 2, "expired": 1 },
    "webhooks": { "processed": 8, "sent": 8, "failed": 0, "dropped": 0 },
    "cleanup": "ok"
  },
  "duration_ms": 1842
}
```

Si votre hébergeur ne dispose pas de cron, configurez un service tiers gratuit (cron-job.org, EasyCron, cronless) en pointant sur la même URL toutes les 5 minutes.

## 7. Automatisations : les 9 triggers

Désactivées par défaut, à activer une par une depuis **DataFirefly Push → Automations**. Chaque carte affiche le titre, le corps et les stats. Cliquez sur **Edit** pour personnaliser le wording et les options.

### Variables disponibles

Selon le trigger, vous pouvez insérer dans le titre et le corps :

- `{first_name}` : prénom du client (vide pour les visiteurs anonymes)
- `{cart_total}` : montant du panier abandonné, formaté avec la devise
- `{order_reference}` : référence de commande
- `{order_total}` : montant total de la commande
- `{product_name}` : nom du produit (retour en stock, baisse de prix)
- `{product_price}` : prix actuel du produit
- `{products_count}` : nombre de nouveaux produits (digest)

### Panier abandonné (3 relances)

Trois triggers indépendants : `abandoned_cart_1h`, `abandoned_cart_24h`, `abandoned_cart_72h`. Le module enregistre chaque modification de panier dans `ps_dfpush_cart_watch` et marque le panier converti dès la validation d'une commande. Le cron envoie chaque relance à maturité, sauf si le panier a été converti entre-temps.

### Retour en stock

Sur la fiche produit, un bouton _Notify me when back in stock_ apparaît automatiquement quand le produit est en rupture. L'abonné clique, son opt-in push est demandé si nécessaire, puis le module enregistre un watcher dans `ps_dfpush_product_watch`. Dès qu'une modification de stock ramène la quantité disponible au-dessus de 0, le watcher est notifié et marqué comme traité.

### Baisse de prix

Même principe avec le bouton _Notify me on price drop_. Le watcher stocke le prix de référence au moment de l'opt-in. La notification est envoyée dès qu'une mise à jour produit fait passer le prix sous 99 % du prix de référence (un seuil qui évite les déclenchements parasites lors des arrondis).

### Confirmation de commande

Déclenchée par le hook `actionValidateOrder`. Envoyée immédiatement, sans respect des heures de silence (transactionnel). Lien direct vers la page de détail de la commande.

### Expédition

Déclenchée par `actionOrderStatusUpdate` dès que le statut passe à un état marqué _shipped_ dans PrestaShop. Lien vers le détail de commande (qui contient le tracking si vous utilisez un module de suivi).

### Demande d'avis

Programmée X jours après le passage de la commande à un état _delivery_ (par défaut 7 jours, configurable dans le JSON config du trigger). La notification est enfilée avec un `scheduled_at` futur, le cron la délivre quand l'heure arrive.

### Anniversaire

Le cron lit le champ `birthday` du client PrestaShop et envoie la notification le jour J à l'heure configurée. Un dédoublonneur évite plusieurs envois la même année.

### Inactivité

Identifie les abonnés dont `last_visit` remonte à plus de N jours (par défaut 30). Pour éviter le harcèlement, un même abonné n'est notifié au maximum qu'une fois tous les 30 jours via ce trigger.

### Nouveaux produits

Digest quotidien envoyé à une heure configurable (par défaut 10 h). Le module agrège les produits créés dans les 24 dernières heures et envoie une notification mentionnant le nom du premier et le nombre total. Idéal pour une boutique qui ajoute régulièrement du catalogue.

## 8. Builder de campagnes

Pour les opérations ponctuelles : **DataFirefly Push → Campaigns → New campaign**. Le formulaire est divisé en cinq sections.

### Contenu

- **Campaign name** : nom interne (jamais affiché aux abonnés)
- **Notification title** : 80 caractères max
- **Body** : 250 caractères max
- **Click URL** : où le clic redirige
- **Icon URL** : petit logo (par défaut votre logo boutique)
- **Large image URL** : image hero, 1024 × 512 recommandé (Chrome uniquement)
- **Badge URL** : PNG monochrome 72 × 72 (Android)

### Boutons d'action

Jusqu'à deux boutons avec leur libellé et URL. Ils apparaissent sous la notification sur Chrome desktop et Android. Idéal pour proposer plusieurs CTA (_Voir l'offre_ / _Ignorer_).

### Audience

Voir la section Segmentation ci-après.

### Schedule & delivery

- **Send at** : date / heure de l'envoi. Vide = immédiat (à la prochaine drainage du cron).
- **Urgency** : `very-low`, `low`, `normal`, `high`. Influe sur la priorité côté push service.
- **TTL** : temps de vie en secondes (par défaut 86400 = 24 h). Si le navigateur de l'abonné est hors ligne plus longtemps, la notification expire.
- **Require interaction** : notification persistante jusqu'à clic ou fermeture manuelle (Chrome uniquement).

## 9. Segmentation

Combinable avec ET logique. Tous les critères vides = aucune restriction.

| Critère | Effet |
| --- | --- |
| Languages | L'abonné parle au moins une de ces langues (cases cochées) |
| Countries | Pays détecté à l'inscription (basé sur la langue / IP / geo) |
| Devices | mobile / desktop / tablet (détecté à l'inscription) |
| Browsers | Chrome, Firefox, Safari, Edge, Opera, Samsung Internet |
| Customer groups | L'abonné est lié à un client PrestaShop dans au moins un des groupes |
| Purchase history | _Any_ (défaut), _Has bought_, _Never bought_ |
| Active within N days | Dernière visite il y a moins de N jours (basé sur `ps_dfpush_customer_activity`) |

Le bouton **Preview audience size** calcule en AJAX le nombre exact d'abonnés correspondants. Utile pour vérifier qu'un ciblage n'est pas trop restrictif avant l'envoi.

## 10. A/B testing

Sur chaque campagne, le champ **% of audience for variant B** définit la part de l'audience qui reçoit la variante B (de 0 à 50). La répartition est déterministe : pour un `id_subscriber` donné, l'abonné reçoit toujours la même variante (basé sur `id_subscriber % 100 < split`).

La variante B override seulement les champs renseignés. Vous pouvez par exemple ne changer que le titre, ou ne tester qu'une image. Les statistiques sont stockées séparément :

- `stats_delivered` / `stats_clicked` / `stats_revenue` : variante A
- `stats_b_delivered` / `stats_b_clicked` / `stats_b_revenue` : variante B

Les colonnes apparaissent dans la liste des campagnes avec un badge _A/B_ à côté du nom.

## 11. Attribution du chiffre d'affaires

Mécanisme clé du module : relier les commandes aux notifications qui les ont déclenchées.

### Flux

1. Le module envoie une notification avec un `track_token` unique (32 caractères hex) en payload.
2. Le service worker intercepte le clic et redirige vers `/module/dfpushnotifications/track?t=TOKEN&click=1&u=URL`.
3. Le contrôleur `track` pose un cookie `dfpush_attr=TOKEN` (30 jours, SameSite=Lax) et redirige vers l'URL finale.
4. Le client navigue, ajoute au panier, valide la commande.
5. Au hook `actionValidateOrder`, l'`AttributionService` lit le cookie, retrouve la notification dans `ps_dfpush_notifications`, écrit `id_order` + `revenue` + `currency` sur la ligne.
6. Le service incrémente `stats_revenue` (ou `stats_b_revenue` selon la variante) sur la campagne ou le trigger, déclenche le webhook `order.attributed`, puis efface le cookie.

### Limites de l'attribution

- Fenêtre fixe à 30 jours. Au-delà, l'attribution n'a plus lieu.
- Un seul cookie par abonné. Si l'utilisateur clique sur une seconde notification avant de commander, c'est la dernière qui est créditée (modèle _last click_).
- L'attribution exige que le clic et la commande aient lieu sur le même navigateur (le cookie est lié au navigateur).
- Une commande déjà attribuée ne peut pas être réattribuée (champ `id_order > 0` bloque la double comptabilisation).

## 12. Topics

Les topics sont des canaux d'abonnement thématiques que les clients activent depuis leur compte. Exemple : _Promotions_, _Nouveaux produits_, _Alertes stock_. Un abonné qui ne coche que _Promotions_ ne recevra que les campagnes ciblant ce topic.

### Créer un topic

1. **DataFirefly Push → Topics → New topic**
2. **Code** : identifiant interne sans espaces (ex. `flash_deals`)
3. **Display order** : position dans la liste affichée au client
4. **Active** : visible des clients
5. **Default opt-in** : pré-coché au moment de l'inscription
6. **Translations** : un nom et une description par langue installée

### Cibler un topic dans une campagne

La segmentation inclut un critère _Topics_ dans le résolveur. Pour l'activer depuis l'UI : actuellement uniquement via JSON personnalisé (la case à cocher Topics arrive dans une mise à jour mineure). Les abonnés sans aucun topic souscrit reçoivent tout (rétrocompatibilité).

## 13. Inbox in-app

L'endpoint `/module/dfpushnotifications/inbox` retourne les 20 dernières notifications du subscriber courant en JSON. Le frontend ouvre cette inbox via la modale unifiée accessible depuis le compte client (tile _Push notifications_).

La modale affiche aussi le statut de souscription (avec bouton subscribe / unsubscribe) et la liste des topics. Pour l'appeler manuellement depuis votre thème :

```
// Ouvrir la modale
window.dfpush.openManagePopup();

// Vérifier l'état d'abonnement
const isOn = window.dfpush.isSubscribed();
```

## 14. Webhooks

Les webhooks envoient les événements du module vers Zapier, Make, n8n ou votre propre backend. Chaque webhook est signé HMAC-SHA256 sur le corps brut de la requête.

### Créer un webhook

1. **DataFirefly Push → Webhooks → New webhook**
2. **URL** : votre endpoint (HTTPS recommandé)
3. **Secret** : généré automatiquement, copiez-le côté receveur
4. **Events** : cochez les événements à délivrer parmi les 8 disponibles
5. Cliquez sur **Send test ping** pour vérifier que votre endpoint répond bien 2xx

### Événements disponibles

- `subscriber.subscribed` : nouvel opt-in
- `subscriber.unsubscribed` : désabonnement
- `subscriber.expired` : push service a renvoyé 410 Gone
- `notification.sent` : notification délivrée avec succès
- `notification.clicked` : clic enregistré
- `notification.failed` : échec définitif après 3 tentatives
- `campaign.sent` : campagne terminée
- `order.attributed` : commande reliée à une notification

### Format du payload

```
{
  "event": "notification.clicked",
  "timestamp": "2026-05-28T14:32:18+00:00",
  "shop": 1,
  "data": {
    "id_subscriber": 482,
    "id_campaign": 12,
    "id_trigger": 0,
    "id_notification": 9182,
    "track_token": "abc123...",
    "url": "https://votreshop.com/promotions",
    "ab_variant": "A"
  }
}
```

### Headers HTTP envoyés

- `Content-Type: application/json`
- `X-DfPush-Event: notification.clicked`
- `X-DfPush-Signature: sha256=`
- `X-DfPush-Timestamp: 1748443938`
- `User-Agent: DataFireflyPush/1.2`

### Vérifier la signature côté receveur

Exemple PHP :

```
$body     = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, $YOUR_SECRET);
$received = explode('=', $_SERVER['HTTP_X_DFPUSH_SIGNATURE'])[1] ?? '';
if (!hash_equals($expected, $received)) {
    http_response_code(401);
    exit;
}
// Signature valide, traiter la payload
$payload = json_decode($body, true);
```

### Retry et drop

Si votre endpoint répond autre chose que 2xx, le module retente avec un backoff exponentiel jusqu'à 5 tentatives. Après quoi, le log est marqué _dropped_ et l'événement est perdu. Les logs _sent_ et _dropped_ sont purgés après 30 jours.

## 15. Multi-boutique et multilingue

Tous les abonnés, campagnes, automatisations, topics et webhooks sont rattachés à un `id_shop`. En multi-boutique :

- Sélectionnez la boutique cible dans le sélecteur du back-office avant de créer une campagne ou une automatisation
- Le cron est unique mais filtre automatiquement par boutique
- Les clés VAPID sont partagées entre boutiques (une seule paire pour toutes)

Côté langue : le module est livré en FR, EN, ES, DE et IT. La langue de l'abonné est détectée à l'inscription et stockée. Vous pouvez segmenter par langue dans les campagnes.

## 16. RGPD et bonnes pratiques

- **Consentement** : la souscription repose sur l'opt-in natif du navigateur, qui est une preuve de consentement RGPD-compatible.
- **Données personnelles** : le module stocke l'endpoint Web Push, l'IP au moment de l'inscription, le user-agent, la langue et le pays. Aucune transmission vers un tiers.
- **Désinscription** : un clic sur le bouton _Unsubscribe_ de la modale ou la désactivation des notifications dans le navigateur met l'abonné en statut `revoked`.
- **Droit à l'effacement** : la suppression d'un compte client en BO supprime aussi ses subscribers liés.
- **Heures de silence** : par défaut 22 h - 8 h. Adaptez à votre cible (B2B = horaires bureau, B2C = soirée).
- **Plafond journalier** : par défaut 3 / jour. Au-delà, taux de désabonnement très élevé.

## 17. Dépannage

### L'opt-in ne s'affiche pas

- Vérifiez que votre site est en HTTPS (pas HTTP).
- Vérifiez que les clés VAPID sont générées (**Settings**).
- Vérifiez que le toggle **Push notifications enabled** est activé.
- Ouvrez la console du navigateur (F12) et cherchez des erreurs côté `dfpush-frontend.js`.
- Si vous avez déjà refusé ou ignoré la demande, le cooldown bloque pendant N jours. Effacez les cookies du domaine pour réinitialiser, ou changez de navigateur pour tester.

### Le cron ne s'exécute pas

- Appelez l'URL manuellement dans votre navigateur : vous devriez voir un JSON avec `success: true`. Si vous voyez un `403 invalid_token`, le token est mal recopié.
- Vérifiez la dernière exécution dans le tableau de bord (**Dashboard**, bloc _System_).
- Sur certains hébergeurs, le timeout cURL des crons est de 30 s. Si la file est très grosse, augmentez la fréquence du cron à toutes les 1 ou 2 minutes pour traiter par plus petits batches.

### Les notifications ne partent pas

- Onglet **Queue** : si les lignes sont en _pending_, c'est que le cron n'a pas tourné depuis leur création.
- Si elles sont en _failed_, cliquez sur la ligne pour voir le code HTTP et le message d'erreur du push service.
- `410 Gone` = l'abonnement n'est plus valide (utilisateur s'est désabonné ou a effacé son navigateur). Le module marque automatiquement le subscriber en _expired_.
- `429 Too Many Requests` = rate limit côté push service. Le module retente automatiquement avec backoff.

### Les commandes ne sont pas attribuées

- Vérifiez que les cookies tiers ne sont pas bloqués par le navigateur du client (mode privé, certains anti-trackers).
- Le cookie expire à 30 jours : une commande passée 31 jours après le clic ne sera pas attribuée.
- Si vous voyez `id_order = 0` dans `ps_dfpush_notifications` alors que la commande a été passée, vérifiez que les hooks `actionValidateOrder` sont bien enregistrés (**Modules → Hooks → actionValidateOrder**).

### Erreur SQL avec "LIMIT 1 LIMIT 1"

Bug interne corrigé en 1.2.0 (`Db::getValue` et `Db::getRow` ajoutent automatiquement leur propre `LIMIT 1`). Si vous voyez encore cette erreur, vérifiez que vous avez bien la dernière version du module installée.

## 18. FAQ

### Combien d'abonnés peut gérer le module ?

Le module n'a pas de limite codée. En pratique, le facteur limitant est le temps d'exécution du cron : sur un hébergement mutualisé standard, comptez environ 50 envois par minute (limité par les push services). Pour 10 000 abonnés, prévoyez un cron toutes les 1 ou 2 minutes pendant l'envoi d'une grosse campagne.

### Safari iOS est-il vraiment exclu ?

Safari iOS supporte le Web Push depuis iOS 16.4 mais uniquement pour les sites installés comme PWA sur l'écran d'accueil. Sur un Safari classique, l'API `Notification` renvoie `undefined`. C'est une limitation Apple, pas du module.

### Puis-je migrer mes abonnés depuis OneSignal ou Firebase ?

Non. Les endpoints push sont liés à la paire de clés VAPID utilisée à l'inscription. Si vous changez de paire, les abonnements existants deviennent invalides. Une migration nécessiterait une réinscription des utilisateurs.

### Le module fonctionne-t-il sur PrestaShop 1.7 ?

Non, uniquement PrestaShop 8.0 à 9.x. La version 1.7 utilise une architecture admin différente qui nécessiterait un fork dédié.

### Puis-je customiser le service worker ?

Oui, le fichier `views/js/sw-template.js` est rendu par le contrôleur `swjs.php` et peut être étendu. Attention : toute modification du service worker nécessite une nouvelle `register()` côté client. Les anciens visiteurs garderont la version précédente jusqu'à ce que le navigateur détecte le changement (généralement 24 h).

### Comment exporter les abonnés ?

Onglet **Subscribers**, bouton **Export CSV**. Le fichier contient endpoint, browser, device, langue, pays, date d'inscription et compteurs d'envoi / clics.

## Support

Pour toute question non couverte par ce guide, contactez le support DataFirefly. Pour signaler un bug, joignez le détail de votre version PrestaShop, PHP et le contenu de la réponse JSON du cron.
