Source: https://cli.nylas.com/guides/track-email-opens-replies-cli

# Track Email Opens, Clicks, and Replies

Enable open, click, and reply tracking when you send email, then receive each event over a webhook — all from the terminal. This guide sends tracked mail, wires the message.opened, message.link_clicked, and thread.replied triggers, verifies the signatures, and explains why open rates overcount.

Written by [Nick Barraclough](https://cli.nylas.com/authors/nick-barraclough) Product Manager

Reviewed by [Qasim Muhammad](https://cli.nylas.com/authors/qasim-muhammad)

Updated June 9, 2026

> **TL;DR:** Send with `--track-opens --track-links`, then create a webhook for `message.opened`, `message.link_clicked`, and `thread.replied`. Verify every payload's signature before trusting it. One of these three signals is far more reliable than the others — the reliability section says which.

## How do I track when someone opens or clicks an email?

You enable tracking at send time with two flags on `nylas email send`: `--track-opens` embeds a tracking pixel, and `--track-links` rewrites links so clicks are recorded. Add `--track-label` to tag a campaign so you can group events later. Tracking is off unless you ask for it.

```bash
nylas email send \
  --to prospect@example.com \
  --subject "Following up" \
  --body "Did you get a chance to review the proposal?" \
  --track-opens --track-links --track-label "q3-outreach" --yes
```

Run `nylas email tracking-info` to see the three event types and the flags that enable them. Opens and clicks are delivered asynchronously over webhooks, not returned inline at send time, so the next step is where the data actually arrives.

## How do I receive open, click, and reply events?

You receive tracking events by registering a webhook for the three tracking triggers. The `nylas webhook create` command points an HTTPS endpoint at `message.opened`, `message.link_clicked`, and `thread.replied` in one call. Each event arrives as a POST with the message ID, a timestamp, and event-specific data.

```bash
nylas webhook create \
  --url https://your-server.example.com/email-tracking \
  --triggers message.opened,message.link_clicked,thread.replied \
  --description "outreach tracking"
```

An open event carries the recipient IP and user agent under a `recents` array; a click event lists each tracked URL with a click count. Your handler should be idempotent, because the same open can be reported more than once as a recipient re-views the message.

## How do I verify tracking webhooks are authentic?

Verify every incoming webhook before you trust its contents — an unauthenticated endpoint will accept forged open and click events from anyone who finds the URL. The `nylas webhook verify` command checks a payload's HMAC-SHA256 signature against your signing secret locally, so you can confirm the mechanism before wiring it into your server.

```bash
# Verify a captured raw payload + signature against your webhook secret
nylas webhook verify \
  --payload-file event.json \
  --signature "$X_NYLAS_SIGNATURE" \
  --secret "$WEBHOOK_SECRET"
```

In production, compute the HMAC-SHA256 of the raw request body with your secret and compare it to the signature header using a constant-time check. Reject any request that doesn't match with a 401 before parsing the body. The dedicated [signature verification guide](https://cli.nylas.com/guides/webhook-signature-verification) shows the server-side code for each language.

## Why are email open rates unreliable?

Open rates overcount because tracking pixels are pre-fetched and blocked, not viewed. Since 2021, Apple's Mail Privacy Protection pre-loads the tracking pixel for every message on receipt, registering an “open” the recipient never made, per [Apple's Mail Privacy Protection documentation](https://support.apple.com/en-us/102420). Corporate image proxies and plain-text clients pull the opposite way, suppressing real opens.

Replies are the reliable signal. A `thread.replied` event requires the recipient to actually respond, so it can't be faked by a pre-fetch or hidden by a proxy. Weight your outreach logic toward replies and clicks, and treat the open rate as a soft directional metric, not a count of human attention.

## How do I test tracking webhooks locally?

Test locally by running the built-in receiver, which prints each event to your terminal so you can inspect the exact payload shape before deploying a handler. The `nylas webhook server` command starts a local endpoint; point a tunnel at it, send a tracked email to yourself, and watch the open and reply events land in real time.

```bash
# Start a local receiver, then send yourself a tracked test email
nylas webhook server --port 9000
```

## Next steps

- [Email read receipts: API options compared](https://cli.nylas.com/guides/email-read-receipts-api) — how open tracking differs from true read receipts
- [Webhook signature verification](https://cli.nylas.com/guides/webhook-signature-verification) — server-side HMAC checks for every language
- [Email webhook events reference](https://cli.nylas.com/guides/email-webhook-events-reference) — every trigger type and its payload
- [Test email webhooks locally](https://cli.nylas.com/guides/test-email-webhooks-locally) — tunnel events to your machine during development
- [Command reference](https://cli.nylas.com/docs/commands) — every flag, subcommand, and example
- [Apple Mail Privacy Protection](https://support.apple.com/en-us/102420) — why pixel-based open tracking overcounts since 2021
- [Images in Gmail](https://support.google.com/mail/answer/145919) — Gmail proxies and caches images, which also distorts open counts
