Template analytics
A template you reuse — an order confirmation, an appointment reminder, a promo blast — accumulates engagement history spread across every campaign that sent it. Template analytics consolidates that history: one rollup that answers “which message actually converts” without opening each campaign individually.GET /api/v1/templates/{id}/analytics returns the template’s cross-campaign totals and rates, plus a per-campaign funnel so you can see where engagement came from.
What the rollup returns
The response carries four blocks:template— the template’sid,name,channel, andstatus, so the rollup is self-describing.totals— cross-campaign counters:campaigns(how many campaigns used the template),sent,delivered,failed,terminal,opened,clicked.rates— conversion fractions rounded to two decimals (0.42 = 42%):delivery_rate= delivered / terminalopen_rate= opened / deliveredclick_rate= clicked / delivered
campaigns— one row per campaign that references the template, newest first, each with its channel andsent → delivered → failed → opened → clickedfunnel.
- Terminal is the denominator, not sent. Delivery rate divides delivered by terminal messages — messages that reached a final state. A campaign still sending reports a lower, honest rate instead of a padded one, because in-flight rows never inflate the denominator.
degraded: truemeans “no data right now,” not “zero engagement.” During a transient database wobble the API serves a zeroed fallback withdegraded: truerather than an error. Treat that response as “try again shortly” — a template with a real history never shows zeros on a healthy read.
Query the rollup
Fetch the analytics for one template by id:cURL
Node.js
Browser (web SDK)
Compare two template versions
Editing a template’s body creates a new version with a new id — the old version’s history stays behind. Fetch analytics for both ids and compare the rates:Node.js
Spot a delivery drop after an edit
When a template edit correlates with worse deliverability, compare per-campaign funnels rather than the lifetime totals — totals blend old and new history. Pull the analytics for the current version and readcampaigns newest-first: the most recent rows are all post-edit sends.
If delivery_rate on recent campaigns sits clearly below the template’s pre-edit level while sent volumes are comparable, the content change is the first suspect — a new URL domain, a shortened link, or reworded copy can change carrier filtering. Check the per-campaign failed counter alongside: a delivery drop with flat failures points at filtering; rising failures point at rejects (inspect the campaign’s error breakdown for codes).
Break down by channel
Templates with the same copy on SMS and WhatsApp rarely perform identically. Thecampaigns rows each carry channel, so group and aggregate client-side:
Node.js
Troubleshooting
- All zeros with
degraded: true. A transient database blip served the fallback. Retry; persistent degradation means contact support, not that the template has no history. campaignsstops at 500 rows. The rollup is a recency-ordered overview, capped at the 500 most recent campaigns. Older campaigns still exist — read them through the campaigns API if you need the full archive.open_rateis 0 on SMS/WhatsApp sends. Opens are recorded only where the channel reports them: email opens via tracking, chat-channel reads via read receipts. SMS has no open signal, soopenedstays 0 andopen_ratefollows.- 404 on the call. The template id does not exist in your tenant (or was deleted). List templates via
GET /api/v1/messages/templatesto confirm the id.
Related
- Template analytics endpoint — request and response reference.
- WhatsApp channel — template management, approval flow, and broadcast limits.
- A/B test a campaign — compare message variants inside one campaign instead of across template versions.
- Delivery log — message-level delivery records behind the campaign counters.