WhatsApp Business
Datafly Signal sends approved WhatsApp template messages server-to-server from first-party events: an order confirmation on purchase, a shipping update on order_shipped, a welcome message on sign_up. Utility templates go through the WhatsApp Cloud API (/messages); marketing templates go through Meta’s Marketing Messages API (/marketing_messages), which accepts marketing templates only.
Every delivered event sends a real, billed WhatsApp message. Nothing is sent until you turn on Send messages (send_enabled), and then only to users whose identify traits carry whatsapp_opt_in: true. Templates must be approved in WhatsApp Manager, and their names and placeholders must match the preset (edit the preset to your templates).
Why route WhatsApp Business through Datafly Signal
- Messages fire from the server, not the browser. An order confirmation is sent when the order event reaches Signal, even when a tracker blocker or a closed tab would have dropped a client-side call.
- One place to gate sends. The operator switch, the user’s WhatsApp opt-in and the phone number are checked before any request leaves Signal.
Prerequisites
Create a WhatsApp Business Account
- In Meta Business Suite, go to Business Settings > Accounts > WhatsApp Accounts.
- Create or select a WhatsApp Business Account and add a phone number.
- Complete phone-number verification.
Find your Phone Number ID
Open WhatsApp Manager > API Setup and note the Phone Number ID (numeric, like 1059xxxxxxxxxxx). This is not the display phone number.
Create a System User and Access Token
- Go to Business Settings > Users > System Users and add a system user with the Admin role.
- Click Add Assets, select your WhatsApp Business Account, and grant full control.
- Click Generate New Token, select the
whatsapp_business_messagingpermission, and copy the token.
Create and approve your templates
The default preset uses these templates. Create them (or rename the preset’s templates to yours) in WhatsApp Manager > Message Templates:
| Template | Category | Body placeholders |
|---|---|---|
order_confirmation | Utility | {{1}} order ID, {{2}} order value, {{3}} currency code |
shipping_update | Utility | {{1}} order ID, {{2}} carrier, {{3}} tracking number |
welcome | Marketing | {{1}} first name |
abandoned_cart (off by default) | Marketing | {{1}} cart value, {{2}} currency code |
The number of parameters must match the approved template exactly, or WhatsApp rejects the message.
Enrol in Marketing Messages
Marketing templates go to /marketing_messages, which needs the Marketing Messages API enabled for the WhatsApp Business Account. Utility templates use the Cloud API and do not need it.
Configuration
| Field | Required | Description |
|---|---|---|
phone_number_id | Yes | Your WhatsApp Business phone number ID (numeric), from WhatsApp Manager > API Setup. |
access_token | Yes | System-user access token with the whatsapp_business_messaging permission. |
send_enabled | Yes, to send | Send messages. Off by default. While it is off, every event is dropped and nothing is sent. |
default_language | Yes | The templates’ language code (for example en_GB). Must match the approved templates. |
api_version | Yes | Graph API version in the endpoint path, for example v23.0. |
template_name | No | Fallback template for an event that does not name its own. The preset names one per event. |
Configure in Signal
- Go to Integrations > Add Integration > WhatsApp Business.
- Enter
phone_number_id,access_token,default_languageandapi_version. - Check the preset’s template names and parameters against your approved templates.
- Click Save, test with your own opted-in number, then turn on Send messages (
send_enabled).
API Endpoints
POST https://graph.facebook.com/{api_version}/{phone_number_id}/messages (utility templates)
POST https://graph.facebook.com/{api_version}/{phone_number_id}/marketing_messages (marketing templates)
Authorization: Bearer {access_token}
Content-Type: application/jsonBoth take the same body. The Marketing Messages endpoint supports only marketing template messages; utility templates sent to it are rejected, so the preset routes order_confirmation and shipping_update to /messages.
Identity and opt-in
WhatsApp must deliver the message to a real handset, so the recipient is the phone number in clear, digits only (E.164 without +). It is never hashed.
| Signal | Field | Description |
|---|---|---|
phone trait | to | Normalised to digits-only E.164 (for example 447700900123). No phone, no send. |
whatsapp_opt_in trait | (gate) | Must be true. WhatsApp’s Business Messaging Policy requires the user’s opt-in to messages from your business. Cookie consent is not that opt-in and is never used for it. |
| Event ID | biz_opaque_callback_data | WhatsApp echoes it in delivery and read webhooks, so outcomes tie back to the event. |
Record the opt-in when the user gives it:
datafly.identify("user-123", {
phone: "+44 7700 900123",
first_name: "Jane",
whatsapp_opt_in: true
});Event Mapping
| Signal event | Template | Endpoint | Default |
|---|---|---|---|
purchase | order_confirmation | /messages | On |
order_shipped | shipping_update | /messages | On |
sign_up | welcome | /marketing_messages | On |
begin_checkout | abandoned_cart | /marketing_messages | Off: begin_checkout fires when checkout starts, so enabling it sends at once, not after the cart is abandoned |
Every other event is dropped.
Example: Order confirmation
Datafly.js call:
datafly.track("purchase", {
transaction_id: "ORD-001",
value: 129.99,
currency: "gbp"
});Request sent by Signal (to /messages):
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "447700900123",
"type": "template",
"biz_opaque_callback_data": "3f1c2a90-7d4e-4b8a-9c61-2f0e5d7a1b22",
"template": {
"name": "order_confirmation",
"language": { "code": "en_GB" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "ORD-001" },
{ "type": "text", "text": "129.99" },
{ "type": "text", "text": "GBP" }
]
}
]
}
}Testing
- Turn on Send messages only after the templates are approved.
- Identify a test user with your own number and
whatsapp_opt_in: true, then trigger a testpurchase. - The message should arrive within seconds. Check WhatsApp Manager > Insights and Signal’s event debugger.
Troubleshooting
| Problem | Solution |
|---|---|
| Nothing is sent, no error | Turn on Send messages (send_enabled). Then check the user has a phone trait and whatsapp_opt_in: true. |
(#132000) template name does not exist | The template name or language does not match an approved template. Edit the preset or default_language. |
(#132012) parameter count mismatch | The template’s {{n}} placeholders do not match the parameters the event sends. Edit the preset. |
Utility template rejected on /marketing_messages | Route the event to the Cloud API: set the event’s endpoint to cloud in the preset. |
(#131047) / (#470) | The user is outside the messaging window or has not opted in. |
(#190) / OAuthException | The access token is invalid, expired, or lacks whatsapp_business_messaging. |
404 on the endpoint | Wrong phone_number_id or api_version, or the account is not enrolled in Marketing Messages. |
Rate Limits
WhatsApp sustains up to about 500 messages per second per phone number; Signal throttles conservatively below that. Volume is also governed by your number’s messaging tier.