Skip to content

Templates

WhatsApp only lets you start a conversation, or message a customer more than 24 hours after they last wrote to you, with a template Meta has approved.

Sending templates

php
// Fill the body placeholders {{1}} and {{2}}
Whatsapp::sendTemplateMessage('15551234567', 'order_shipped', ['Sarah', '#1042']);

// Use a different language version
Whatsapp::sendTemplateMessage('15551234567', 'order_shipped', ['Sara', '#1042'], language: 'es_ES');

The language defaults to the tenant's language, then WHATSAPP_DEFAULT_LANGUAGE (en_US). Language codes use an underscore, like en_US or pt_BR.

Media headers

Pass header parameters in the shape the API expects:

php
Whatsapp::sendTemplateMessageWithComponents(
    to: '15551234567',
    templateName: 'order_shipped_with_photo',
    bodyParameters: ['Sarah', '#1042'],
    headerParameters: [
        ['type' => 'image', 'image' => ['link' => 'https://example.com/parcel.jpg']],
    ],
);

Use ['type' => 'image', 'image' => ['id' => $mediaId]] for uploaded media, and video or document the same way. Footers are fixed text and take no parameters.

Buttons

Templates with dynamic URL buttons or quick replies are easier to build with the template builder:

php
$template = Whatsapp::template('delivery_update')
    ->body(['Sarah', 'Thursday'])
    ->button('url', ['tracking/1042'], index: 0)
    ->build();

Whatsapp::sendMessage('15551234567', $template);

index is the button's position in the template, starting at 0. When a customer taps a quick-reply button, $event->buttonPayload() on MessageReceived returns its payload.

Creating templates

Managing templates needs WHATSAPP_BUSINESS_ACCOUNT_ID.

php
$template = Whatsapp::createTemplate('order_shipped', 'en_US', 'UTILITY', [
    ['type' => 'HEADER', 'format' => 'TEXT', 'text' => 'Your order is on its way'],
    ['type' => 'BODY', 'text' => 'Hi {{1}}, order {{2}} has shipped.', 'example' => ['body_text' => [['Sarah', '#1042']]]],
    ['type' => 'FOOTER', 'text' => 'Reply STOP to opt out'],
]);

$template['status']; // PENDING

The category must be MARKETING, UTILITY or AUTHENTICATION. Every template needs a BODY component. The package checks these before calling the API.

New and edited templates go to Meta for review automatically; there's no separate publish step.

Image, video and document headers

Templates with a media header need a sample file when you create them. Upload it first, which needs WHATSAPP_APP_ID:

php
$handle = Whatsapp::uploadTemplateMedia(storage_path('app/samples/parcel.jpg'));

Whatsapp::createTemplate('order_shipped_with_photo', 'en_US', 'UTILITY', [
    ['type' => 'HEADER', 'format' => 'IMAGE', 'example' => ['header_handle' => [$handle]]],
    ['type' => 'BODY', 'text' => 'Hi {{1}}, order {{2}} has shipped.', 'example' => ['body_text' => [['Sarah', '#1042']]]],
]);

The sample can be a JPEG, PNG, MP4 or PDF file.

Checking review status

php
Whatsapp::getTemplateStatus('order_shipped');   // APPROVED, PENDING, REJECTED, PAUSED, ...
Whatsapp::isTemplateApproved('order_shipped');
Whatsapp::isTemplatePending('order_shipped');

Rather than polling, listen for the TemplateStatusUpdated event, which Meta sends as soon as a review finishes. From the terminal, php artisan whatsapp:templates --status=rejected lists rejected templates.

Listing templates

php
Whatsapp::getTemplates();                                   // one page, with paging cursors
Whatsapp::getTemplates(['limit' => 100, 'after' => $cursor]);
Whatsapp::getTemplatesByStatus('REJECTED');
Whatsapp::getTemplatesByCategory('MARKETING');
Whatsapp::getTemplatesByLanguage('es_ES');
Whatsapp::getTemplate('order_shipped');                     // searches every page

Editing and deleting

php
// Replaces all components of the en_US version and sends it for review again
Whatsapp::updateTemplate('order_shipped', 'en_US', 'UTILITY', $components);

// Deletes every language version
Whatsapp::deleteTemplate('order_shipped');

Meta limits how often an approved template can be edited, so it's worth getting templates right before they're approved.

Released under the MIT License. Not affiliated with Meta or WhatsApp.