Aller à la documentation
Ruby

Suivi des ouvertures et des clics

`emails.get_tracking` et tout l'espace de noms `tracking`.

Un message

tracking.rb
report = client.emails.get_tracking("msg_3f9a1c07d2b84e6a9c5b1f20") puts "#{report[:openCount]} opens from #{report[:recipients].size} recipients"report[:links].each { |link| puts "#{link[:url]} #{link[:clickCount]}" }

Un message qui n'a jamais été suivi lève une OpenEmail::NotFoundError, dont not_found? vaut true, et non un rapport vide. « Nous n'avons rien enregistré » et « personne ne l'a ouvert » sont deux réponses différentes et ne doivent pas se partager une même réponse. Un message envoyé avec une clé de test n'est jamais suivi : il en lève donc toujours une.

Sur l'ensemble de la boîte

tracking_report.rb
client.tracking.list(opened: false, days: 7, limit: 100)client.tracking.get_stats(days: 30, offset_minutes: Time.now.utc_offset / 60)client.tracking.get("msg_3f9a1c07d2b84e6a9c5b1f20")client.tracking.list_opens("msg_3f9a1c07d2b84e6a9c5b1f20", include_machine: true)client.tracking.list_clicks("msg_3f9a1c07d2b84e6a9c5b1f20")

list, list_opens et list_clicks renvoient une OpenEmail::Page, et list_all, iterate, list_all_opens, iterate_opens, list_all_clicks et iterate_clicks parcourent toutes les pages pour vous. get, list_opens et list_clicks acceptent soit l'id d'envoi msg_…, soit le tmsg_… propre à l'enregistrement de suivi.

Un espace de noms à part entière plutôt que des méthodes sur emails, et la raison est la couverture : emails liste des enregistrements d'envoi, qui n'existent que pour le courrier traité par cette API. Le composer, les outils MCP et l'assistant envoient tous sans en créer : un rapport bâti sur emails serait donc un rapport sur votre trafic API plutôt que sur la boîte.

Lire les chiffres honnêtement

PaireCe que cela signifie
opens et clicksCe qui a été APPLIQUÉ : si le message est parti avec un pixel ou des liens réécrits.
opened et clickedCe qui s'est passé.
openCountLes hits comptabilisés. Scanners et proxys de confidentialité exclus.
openCountRawTous les hits. C'est en citant ce chiffre comme engagement qu'un taux d'ouverture dépasse 100 %.
attributableSi une lecture peut seulement être rattachée à un destinataire nommé.

Les taux de tracking.get_stats portent sur les messages SUIVIS, jamais sur tout ce qui a été envoyé. Sinon, une boîte qui suit un message sur dix semblerait s'être effondrée. openRate et clickRate sont des pourcentages arrondis à une décimale, comme 42.5, et non des fractions entre 0 et 1.

Paramètres : tracking.list

openedBoolean
`true` sélectionne les messages ayant au moins une ouverture comptabilisée, `false` sélectionne les messages suivis qui n'en ont aucune. Aucune des deux valeurs n'est un défaut, et `false` ne désigne jamais le courrier non suivi, qui n'apparaît pas du tout dans cette liste.
clickedBoolean
Le même filtre pour les clics comptabilisés, appliqué indépendamment d'`opened`. Les deux peuvent être fournis, et les messages doivent satisfaire les deux.
daysInteger
Sur combien de jours en arrière regarder à partir de maintenant, de 1 à 365, 30 par défaut, et hors de cette plage, c'est un 422. La fenêtre se mesure sur la date de création de l'enregistrement de suivi, et seuls les enregistrements dont l'envoi est réellement parti sont listés.
minutesInteger
La fenêtre en minutes à la place, de 1 à 527040, qui l'emporte sur `days` quand les deux sont définis. Une fenêtre de moins d'un jour demande un `grain` plus fin.
grainString
`minute`, `hour` ou `day`, `day` par défaut. Il ne fait qu'arrondir vers le bas le début de la fenêtre, pour que cette liste corresponde à `get_stats` lu avec le même grain, et ne façonne rien dans la réponse.
limitInteger
Rapports par page, de 1 à 200, 50 par défaut, du plus récent au plus ancien. Renvoyez le `next_cursor` de la page comme `cursor:`, avec les mêmes filtres, pour obtenir la suivante, ou laissez `list_all` et `iterate` parcourir toute la fenêtre.
cursorString
Le `next_cursor` de la page précédente, un id `tmsg_`.
api_keyString
Liste avec cette clé au lieu de celle du client.

Réponse : le rapport de suivi

emails.get_tracking et tracking.get renvoient un rapport sous forme de Hash à clés Symbol, et tracking.list en renvoie une page.

objectString
Toujours `tracking` sur un rapport récupéré pour lui-même, via `tracking.get`, `tracking.list` ou `emails.get_tracking`. Le même rapport imbriqué sous `tracking` sur un message issu d'`emails.get` arrive sans cette clé, car il y fait partie de ce message au lieu d'avoir été récupéré.
idString
L'id propre à l'enregistrement de suivi, `tmsg_…`. C'est sur lui que sont indexés `list_opens` et `list_clicks`, et un `msg_…` qui leur est transmis est d'abord résolu vers celui-ci.
sendIdString or nil
L'envoi `msg_…` auquel cet enregistrement se rattache, et nil quand aucun enregistrement d'envoi n'a été écrit. Le composer, le `sendEmail` de MCP et l'assistant envoient tous sans en créer. Le suivi couvre la boîte, pas seulement le trafic API.
threadIdString or nil
Renseigné après la transmission pour qu'une interface de lecture puisse retrouver le message, et nil quand le driver n'en a rapporté aucun. Pas structurant : un enregistrement où il vaut nil compte quand même.
messageIdString or nil
Le Message-ID RFC 5322, pas notre id. Également renseigné après la transmission, et nil quand le transport n'a rien renvoyé pour le remplir.
subjectString or nil
L'objet tel qu'il était au moment de l'envoi. nil sur un message enregistré sans objet.
fromString
L'adresse d'expédition, copiée sur l'enregistrement plutôt que jointe depuis l'envoi. Les rapports se lisent longtemps après coup, et une adresse corrigée ou supprimée depuis réécrirait sinon l'histoire.
sourceString
Quelle surface l'a envoyé : `composer`, `api`, `mcp`, `ai` ou `queue`. Une surface que cette gem ne nomme pas encore peut apparaître : traitez donc une valeur inconnue comme une information plutôt que comme une erreur.
sentAtString or nil
Quand le message est parti, sous forme d'instant ISO 8601. nil sur un enregistrement dont l'envoi ne s'est jamais terminé. `tracking.list` les exclut, `get` non.
opensBoolean
Indique si un pixel a été APPLIQUÉ à ce message. C'est ce qui a été fait, pas ce que dit aujourd'hui le réglage du compte.
clicksBoolean
Indique si les liens de ce message ont été réécrits. False quand le corps ne portait aucun lien, car rien n'a alors été modifié et un enregistrement prétendant le contraire ne pourrait pas être réconcilié avec les octets.
openedBoolean
Indique si une ouverture comptabilisée a été enregistrée sur l'ensemble des copies. À lire en regard d'`opens` : aucune donnée parce qu'aucune n'a été collectée est un fait différent de personne n'a lu le message.
clickedBoolean
Indique si un clic comptabilisé a été enregistré. Preuve plus solide qu'une ouverture, car les images sont bloquées bien plus souvent que les liens ne restent inexplorés.
attributableBoolean
Indique si chaque lecture rapportée ici peut être rattachée à un destinataire nommé. False dès qu'une copie non attribuée présente une activité comptabilisée, c'est-à-dire le cas multi-destinataires où un seul corps part vers toute la liste sous un même token : vérifiez-le avant d'écrire « Bob n'a pas ouvert ce message ».
openCountInteger
Les ouvertures jugées causées par une personne, additionnées sur les copies. Les hits machine sont exclus et les répétitions dans les trente secondes fusionnent en une seule : c'est donc le chiffre à mettre sous les yeux d'un lecteur.
clickCountInteger
Les clics comptabilisés, additionnés sur les copies. Dédupliqués par lien et non par message : deux liens différents suivis à quelques secondes d'intervalle comptent donc pour deux clics.
openCountRawInteger
Tous les chargements du pixel, scanners et proxys de confidentialité compris. `openCountRaw` moins `openCount` donne le nombre de chargements écartés, accès automatisés et répétitions en moins de trente secondes confondus, et c'est la seule preuve disponible que le filtrage a bien eu lieu.
clickCountRawInteger
Toutes les visites sur un lien réécrit, hits machine et répétitions compris.
firstOpenAtString or nil
La première ouverture comptabilisée parmi les copies, et nil tant qu'il n'y en a aucune. Les accès automatisés ne la déplacent jamais.
lastOpenAtString or nil
La dernière ouverture comptabilisée parmi les copies, nil tant qu'il n'y en a aucune.
firstClickAtString or nil
Le premier clic comptabilisé parmi les copies, nil tant qu'il n'y en a aucun.
lastClickAtString or nil
Le dernier clic comptabilisé parmi les copies, nil tant qu'il n'y en a aucun.
recipientsArray<Hash>
Une entrée par copie suivie : une par destinataire quand le transport permet aux octets de différer d'une personne à l'autre, et une seule entrée partagée quand il ne le permet pas. L'entrée partagée est écartée sauf si quelque chose y a réellement atterri : une ligne « quelqu'un » restée intacte ne côtoie donc jamais de vrais noms.
linksArray<Hash>
Tous les liens réécrits dans ce message, ordonnés selon leur position dans le corps. Vide quand il n'y en a eu aucun : un message envoyé avec `clicks` désactivé, ou un message dont le corps ne portait aucun lien.

Chaque entrée de recipients

emailString or nil
À qui cette copie est allée, en minuscules et telle qu'elle était au moment de l'envoi. nil exactement quand `attributed` vaut false.
kindString or nil
`to`, `cc` ou `bcc` : sur quel en-tête l'adresse figurait, pour qu'un rapport se lise comme se lisait le message. nil sur la copie partagée, qui n'appartient à aucune adresse.
attributedBoolean
Indique si cette ligne nomme une personne. À lire avant `email` : false désigne la copie partagée, listée dès qu'un hit y atterrit, et mettre un nom sur ce hit, même sur un message à destinataire unique, inventerait le seul fait que le mécanisme ne peut pas fournir.
openCountInteger
Les ouvertures comptabilisées sur cette seule copie, sous les mêmes exclusions que le total du message : hits machine écartés, et répétitions dans les trente secondes fusionnées en une seule.
clickCountInteger
Les clics comptabilisés sur cette seule copie, dédupliqués par lien et non par copie.
firstOpenAtString or nil
La première ouverture comptabilisée sur cette copie, nil tant qu'il n'y en a aucune.
lastOpenAtString or nil
La dernière ouverture comptabilisée sur cette copie, nil tant qu'il n'y en a aucune.
firstClickAtString or nil
Le premier clic comptabilisé sur cette copie, nil tant qu'il n'y en a aucun.
lastClickAtString or nil
Le dernier clic comptabilisé sur cette copie, nil tant qu'il n'y en a aucun.

Chaque entrée de links

idString
L'id propre au lien, `lnk_…`. C'est la valeur que désigne le `linkId` d'une ligne de clic, ce qui permet de rattacher un accès issu de `list_clicks` à l'entrée correspondante ici.
urlString
Où mène réellement le lien, tel qu'il figurait dans le message avant réécriture. Le redirecteur résout un id vers cette valeur et envoie le visiteur plus loin.
labelString or nil
Le texte du lien tel qu'il apparaissait dans le message, ou nil quand le lien n'en avait pas, par exemple une image ou une URL nue. Il est là pour qu'un rapport puisse dire « le lien tarifs » au lieu de citer une URL portant trois paramètres de suivi, et il ne remplace jamais `url`.
clickCountInteger
Les visites comptabilisées sur ce lien, additionnées sur les copies. La même fenêtre de trente secondes par lien que `clickCount` sur le message.
clickCountRawInteger
Toutes les visites sur ce lien, hits machine et répétitions compris.