Skip to main content

UC-024 — Templates with Tracked Links

FieldValue
IDUC-024
GoalCreate WhatsApp templates with tracked buttons to measure CTR
ChannelWhatsApp
Complexity⭐⭐⭐ Advanced
Estimated time30 minutes
APIs involvedPOST /api/message-server/whatsapp/templates, POST /api/message-server/whatsapp/send

Real-world scenarios

  • ShopItalia — Measure CTR: Track how many users click the "Go to shop" button in the promotional template to calculate the campaign conversion rate.
  • TravelDream — Landing page tracking: Each recipient receives a unique link to the travel offer landing page, with UTM parameters for Google Analytics analysis.
  • MarketingPro — A/B testing links: Send two template variants with different links (landing A vs landing B) to determine which converts better.

The diagram shows the complete cycle: template creation with tracking, delivery to the recipient and click capture with transparent redirect to the landing page.

Prerequisites

  • Active API Key with WhatsApp template permissions
  • Verified WhatsApp Business number (see UC-025)
  • HTTPS landing page ready for tracking
  • Familiarity with WhatsApp templates (see UC-013)

Create a WhatsApp template with trackButtonLinks: true to enable automatic click tracking.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/templates \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "promo_estate_tracked_2026",
"language": "it",
"category": "MARKETING",
"components": [
{"type": "HEADER", "format": "IMAGE",
"example": {"header_handle": ["https://cdn.shopitalia.it/promo/estate-2026-header.jpg"]}},
{"type": "BODY",
"text": "Ciao {{1}}, i saldi estivi sono arrivati! Sconto {{2}} su tutta la collezione fino al {{3}}.",
"placeholderFields": [
{"index": 1, "label": "Nome cliente", "example": "Marco"},
{"index": 2, "label": "Percentuale sconto", "example": "50%"},
{"index": 3, "label": "Data scadenza", "example": "30 giugno"}]},
{"type": "BUTTONS", "buttons": [
{"type": "URL", "text": "Vai allo shop",
"url": "https://shopitalia.it/promo/estate2026?utm_source=whatsapp&utm_campaign={{1}}",
"example": ["promo_estate"]}]}
],
"trackButtonLinks": true
}'

Response — Template submitted

{
"templateId": "promo_estate_tracked_2026",
"name": "promo_estate_tracked_2026",
"status": "PENDING",
"language": "it",
"category": "MARKETING",
"trackButtonLinks": true,
"createdAt": "2026-04-09T12:00:00+02:00"
}

:::info Meta approval The template must be approved by Meta before use. The process typically takes from a few minutes to 24 hours. Monitor the status with a GET on the template. :::

Behind the scenes — How link tracking works
  1. URL rewriting: When trackButtonLinks: true is active, the gateway replaces the original button URL with an intermediate tracking URL (e.g., https://trk.agiletelecom.com/c/abc123).
  2. Click capture: When the recipient clicks the button, the request passes through the tracking service which records: timestamp, recipient, template, campaign.
  3. Transparent redirect: After recording the click, the tracking service performs an HTTP 302 redirect to the original landing page URL.
  4. UTM parameters: UTM parameters in the original URL are preserved in the redirect, allowing attribution in Google Analytics or other analytics tools.
  5. Available metrics: Total clicks, unique clicks, CTR (clicks/delivered), average time to click, hourly click distribution.

Step 2 — Send the message with tracked template

Once the template is approved, send the message with personalized parameters.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"templateId": "promo_estate_tracked_2026",
"language": "it",
"components": [
{
"type": "HEADER",
"parameters": [
{"type": "image", "image": {"link": "https://cdn.shopitalia.it/promo/estate-2026-header.jpg"}}
]
},
{
"type": "BODY",
"parameters": [
{"type": "text", "text": "Marco"},
{"type": "text", "text": "50%"},
{"type": "text", "text": "30 giugno"}
]
},
{
"type": "BUTTON",
"sub_type": "URL",
"index": 0,
"parameters": [
{"type": "text", "text": "promo_estate"}
]
}
]
}'

Response — Message sent with tracking

{
"messageId": "wa-msg-trk-2026-04-09-001",
"accepted": true,
"destination": "+393471234567",
"templateId": "promo_estate_tracked_2026",
"trackingEnabled": true,
"trackedLinks": [
{
"buttonIndex": 0,
"originalUrl": "https://shopitalia.it/promo/estate2026?utm_source=whatsapp&utm_medium=template&utm_campaign=promo_estate",
"trackingUrl": "https://trk.agiletelecom.com/c/wa-msg-trk-2026-04-09-001-btn0"
}
]
}

:::tip Save the trackingUrls Save the trackingUrl values returned in the response to correlate clicks with individual messages in your analytics system. :::

Expected result

StepActionResult
1POST /whatsapp/templatesTemplate created with trackButtonLinks: true
2Meta approvalStatus APPROVED
3POST /whatsapp/sendMessage sent with tracked links
4Recipient clickEvent recorded + redirect to landing

Complete end-to-end example

# 1. Create template with tracking (one-time, wait for approval)
curl -s -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/templates \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "promo_estate_tracked_2026",
"language": "it",
"category": "MARKETING",
"components": [
{"type": "BODY", "text": "Ciao {{1}}, sconto {{2}} fino al {{3}}!",
"placeholderFields": [
{"index": 1, "label": "Nome", "example": "Marco"},
{"index": 2, "label": "Sconto", "example": "50%"},
{"index": 3, "label": "Scadenza", "example": "30 giugno"}]},
{"type": "BUTTONS", "buttons": [
{"type": "URL", "text": "Vai allo shop", "url": "https://shopitalia.it/promo?c={{1}}", "example": ["estate2026"]}]}
],
"trackButtonLinks": true
}' | jq .

# 2. After approval, send the message
MSG_ID=$(curl -s -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"templateId": "promo_estate_tracked_2026",
"language": "it",
"components": [
{"type": "BODY", "parameters": [{"type": "text", "text": "Marco"}, {"type": "text", "text": "50%"}, {"type": "text", "text": "30 giugno"}]},
{"type": "BUTTON", "sub_type": "URL", "index": 0, "parameters": [{"type": "text", "text": "estate2026"}]}
]
}' | jq -r '.messageId')

echo "Message ID: $MSG_ID"

Variants

Template with multiple tracked buttons

Track clicks on multiple buttons to understand which CTA converts better:

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/templates \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "multi_cta_tracked_2026",
"language": "it",
"category": "MARKETING",
"components": [
{"type": "BODY", "text": "Ciao {{1}}, scopri le nostre offerte!"},
{
"type": "BUTTONS",
"buttons": [
{"type": "URL", "text": "Offerte donna", "url": "https://shop.it/donna?c={{1}}", "example": ["spring"]},
{"type": "URL", "text": "Offerte uomo", "url": "https://shop.it/uomo?c={{1}}", "example": ["spring"]}
]
}
],
"trackButtonLinks": true
}'

Common errors

400 Bad Request — Missing placeholderFields

{
"status": "fail",
"data": {
"placeholderFields": "Placeholder fields are required when body contains variables"
}
}

Solution: Each {{N}} variable in the body text requires a corresponding object in placeholderFields with index, label and example.

400 Bad Request — Invalid button URL

{
"status": "fail",
"data": {
"buttons": "Button URL must be a valid HTTPS URL"
}
}

Solution: The button URL must start with https://. URLs with HTTP protocol or without protocol are rejected.

401 Unauthorized — Missing or invalid API Key

{
"status": "fail",
"data": {
"authentication": "Invalid or missing API key"
}
}

Solution: Verify that the X-Api-Key header is present and that the key is active in the platform dashboard.

Next steps

References