Ir a la documentación
Ruby

Seguimiento de aperturas y clics

`emails.get_tracking` y todo el espacio de nombres `tracking`.

Un mensaje

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 mensaje del que nunca se hizo seguimiento lanza un OpenEmail::NotFoundError, cuyo not_found? es true, y no un informe vacío. «No registramos nada» y «nadie lo abrió» son respuestas distintas y no deben compartir una misma respuesta. Un mensaje enviado con una clave de prueba nunca tiene seguimiento, así que siempre lanza uno.

En todo el buzón

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 y list_clicks devuelven una OpenEmail::Page, y list_all, iterate, list_all_opens, iterate_opens, list_all_clicks e iterate_clicks recorren todas las páginas por ti. get, list_opens y list_clicks aceptan tanto el id de envío msg_… como el tmsg_… propio del registro de seguimiento.

Es un espacio de nombres propio en lugar de métodos en emails, y el motivo es la cobertura: emails lista registros de envío, que solo existen para el correo que gestionó esta API. El redactor, las herramientas MCP y el asistente envían sin uno, así que un informe construido sobre emails sería un informe sobre tu tráfico de API y no sobre el buzón.

Leer las cifras con honestidad

ParQué significa
opens y clicksLo que se APLICÓ: si el mensaje salió con un píxel o con enlaces reescritos.
opened y clickedLo que ocurrió.
openCountVisitas contabilizadas. Se excluyen los escáneres y los proxies de privacidad.
openCountRawTodas las visitas. Citar esto como interacción es la forma de que una tasa de apertura supere el 100 %.
attributableSi una lectura puede atribuirse siquiera a un destinatario concreto.

Las tasas de tracking.get_stats se calculan sobre los mensajes CON SEGUIMIENTO, nunca sobre todo lo enviado. De lo contrario, un buzón que hace seguimiento de uno de cada diez mensajes parecería haberse hundido. openRate y clickRate son porcentajes redondeados a un decimal, como 42.5, no fracciones entre 0 y 1.

Parámetros: tracking.list

openedBoolean
`true` selecciona los mensajes con al menos una apertura contabilizada; `false` selecciona los mensajes con seguimiento que no tienen ninguna. Ninguno es el valor por defecto, y `false` nunca significa correo sin seguimiento, que no aparece en esta lista en absoluto.
clickedBoolean
El mismo filtro para los clics contabilizados, aplicado con independencia de `opened`. Se pueden indicar ambos, y los mensajes deben cumplir los dos.
daysInteger
Cuántos días hacia atrás desde ahora hay que mirar, de 1 a 365 y con 30 por defecto, y fuera de ese rango es un 422. La ventana se mide sobre la fecha de creación del registro de seguimiento, y solo se listan los registros cuyo envío salió realmente.
minutesInteger
La ventana en minutos, de 1 a 527040, que prevalece sobre `days` cuando se indican ambos. Una ventana de menos de un día necesita un `grain` más fino.
grainString
`minute`, `hour` o `day`, con `day` por defecto. Solo redondea hacia abajo el inicio de la ventana, para que esta lista coincida con `get_stats` leído con la misma granularidad, y no da forma a nada de la respuesta.
limitInteger
Informes por página, de 1 a 200 y con 50 por defecto, de más nuevo a más antiguo. Devuelve el `next_cursor` de la página como `cursor:`, con los mismos filtros, para la siguiente, o deja que `list_all` e `iterate` recorran toda la ventana.
cursorString
El `next_cursor` de la página anterior, un id `tmsg_`.
api_keyString
Lista con esta clave en lugar de la del cliente.

Respuesta: el informe de seguimiento

emails.get_tracking y tracking.get devuelven un informe como Hash con claves Symbol, y tracking.list devuelve una página de ellos.

objectString
Siempre `tracking` en un informe obtenido por sí mismo, mediante `tracking.get`, `tracking.list` o `emails.get_tracking`. El mismo informe anidado como `tracking` en un mensaje de `emails.get` llega sin esta clave, porque allí forma parte de ese mensaje en lugar de ser algo que se obtuvo.
idString
El id propio del registro de seguimiento, `tmsg_…`. Es la clave sobre la que operan `list_opens` y `list_clicks`, y un `msg_…` que se les entregue se resuelve antes a este.
sendIdString or nil
El envío `msg_…` con el que se correlaciona, y nil cuando no se escribió ningún registro de envío. El redactor, el `sendEmail` de MCP y el asistente envían todos sin uno. El seguimiento cubre el buzón, no solo el tráfico de la API.
threadIdString or nil
Se rellena tras la transmisión para que una interfaz de lectura pueda volver a encontrar el mensaje, y es nil cuando el driver no informó de ninguno. No es imprescindible: un registro con este campo en nil sigue contando.
messageIdString or nil
El Message-ID de RFC 5322, no nuestro id. También se rellena tras la transmisión, y es nil cuando el transporte no devolvió nada con lo que rellenarlo.
subjectString or nil
El asunto tal como estaba en el momento del envío. nil en un mensaje registrado sin ninguno.
fromString
La dirección de envío, copiada en el registro en lugar de unida desde el envío. Los informes se leen mucho después, y una dirección corregida o eliminada desde entonces reescribiría la historia.
sourceString
Qué superficie lo envió: `composer`, `api`, `mcp`, `ai` o `queue`. Puede aparecer una superficie que esta gema aún no nombra, así que trata un valor desconocido como información y no como un error.
sentAtString or nil
Cuándo salió el mensaje, como instante ISO 8601. nil en un registro cuyo envío nunca se completó. `tracking.list` los excluye, `get` no.
opensBoolean
Si se APLICÓ un píxel a este mensaje. Esto es lo que se hizo, no lo que dice ahora la configuración de la cuenta.
clicksBoolean
Si se reescribieron los enlaces de este mensaje. False cuando el cuerpo no llevaba enlaces, porque entonces no se cambió nada y un registro que afirmara lo contrario no se podría conciliar con los bytes.
openedBoolean
Si se registró alguna apertura contabilizada entre las copias. Léelo junto con `opens`: que no haya datos porque no se recogió ninguno es un hecho distinto de que nadie haya leído el mensaje.
clickedBoolean
Si se registró algún clic contabilizado. Es una prueba más sólida que una apertura, ya que las imágenes se bloquean mucho más a menudo de lo que los enlaces se quedan sin seguir.
attributableBoolean
Si toda lectura recogida aquí puede atribuirse a un destinatario concreto. Es false en cuanto una copia sin atribuir muestra actividad contabilizada, que es el caso de varios destinatarios en el que un mismo cuerpo va a toda la lista bajo un único token, así que compruébalo antes de escribir «Bob no ha abierto esto».
openCountInteger
Aperturas que se cree causadas por una persona, sumadas sobre las copias. Se excluyen las visitas de máquinas y las repeticiones en menos de treinta segundos se agrupan en una, así que esta es la cifra que hay que poner delante de un lector.
clickCountInteger
Clics contabilizados, sumados sobre las copias. Se deduplican por enlace y no por mensaje, así que dos enlaces distintos seguidos con segundos de diferencia son dos clics.
openCountRawInteger
Todas las peticiones del píxel, incluidos los escáneres y los proxies de privacidad. `openCountRaw` menos `openCount` es cuántas se apartaron, entre peticiones de máquinas y repeticiones en menos de treinta segundos, y la única prueba disponible de que el filtrado llegó a ocurrir.
clickCountRawInteger
Todas las visitas a un enlace reescrito, incluidas las de máquinas y las repeticiones.
firstOpenAtString or nil
La primera apertura contabilizada entre las copias, y nil mientras no haya ninguna. Las visitas de máquinas nunca la mueven.
lastOpenAtString or nil
La apertura contabilizada más reciente entre las copias, nil mientras no haya ninguna.
firstClickAtString or nil
El primer clic contabilizado entre las copias, nil mientras no haya ninguno.
lastClickAtString or nil
El clic contabilizado más reciente entre las copias, nil mientras no haya ninguno.
recipientsArray<Hash>
Una entrada por copia con seguimiento: una por destinatario cuando el transporte permite que los bytes difieran por persona, y una única entrada compartida cuando no. La entrada compartida se descarta salvo que realmente haya llegado algo a ella, así que una fila «alguien» sin tocar nunca aparece junto a nombres reales.
linksArray<Hash>
Todos los enlaces que se reescribieron en este mensaje, ordenados por su posición en el cuerpo. Vacío cuando no hubo ninguno: un mensaje enviado con `clicks` desactivado, o uno cuyo cuerpo no llevaba ningún enlace.

Cada entrada de recipients

emailString or nil
A quién fue esta copia, en minúsculas y tal como estaba en el momento del envío. Es nil exactamente cuando `attributed` es false.
kindString or nil
`to`, `cc` o `bcc`: en qué cabecera apareció la dirección, para que un informe se lea igual que se leyó el mensaje. nil en la copia compartida, que no pertenece a ninguna dirección.
attributedBoolean
Si esta fila nombra a una persona. Léelo antes que `email`: false es la copia compartida, que se lista en cuanto le llega cualquier visita, y ponerle un nombre a esa visita, incluso en un mensaje con un solo destinatario, inventaría el único dato que el mecanismo no puede aportar.
openCountInteger
Aperturas contabilizadas solo en esta copia, con las mismas exclusiones que el total del mensaje: se descartan las visitas de máquinas y las repeticiones en menos de treinta segundos se agrupan en una.
clickCountInteger
Clics contabilizados solo en esta copia, deduplicados por enlace y no por copia.
firstOpenAtString or nil
La primera apertura contabilizada en esta copia, nil mientras no haya ninguna.
lastOpenAtString or nil
La apertura contabilizada más reciente en esta copia, nil mientras no haya ninguna.
firstClickAtString or nil
El primer clic contabilizado en esta copia, nil mientras no haya ninguno.
lastClickAtString or nil
El clic contabilizado más reciente en esta copia, nil mientras no haya ninguno.

Cada entrada de links

idString
El id propio del enlace, `lnk_…`. Es el valor que nombra el `linkId` de una fila de clic, de modo que una visita de `list_clicks` puede emparejarse con la entrada de aquí.
urlString
Adónde va realmente el enlace, tal como estaba en el mensaje antes de la reescritura. El redirector traduce un id a esto y envía al visitante a su destino.
labelString or nil
El texto del enlace tal como apareció en el mensaje, o nil cuando el enlace no tenía ninguno, como una imagen o una URL escueta. Está ahí para que un informe pueda decir «el enlace de precios» en lugar de citar una URL con tres parámetros de seguimiento, y nunca sustituye a `url`.
clickCountInteger
Visitas contabilizadas a este enlace, sumadas sobre las copias. La misma ventana de treinta segundos por enlace que `clickCount` en el mensaje.
clickCountRawInteger
Todas las visitas a este enlace, incluidas las de máquinas y las repeticiones.