Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/rahul-baberwal/django-meta-whatsapp/llms.txt

Use this file to discover all available pages before exploring further.

Campaigns let you send a WhatsApp template message to a large audience at once. Each campaign targets a defined audience (contacts, CSV upload, or a custom queryset), maps template variables to audience fields, and tracks delivery, read, and failure counts in real time.

WhatsAppCampaign model fields

FieldTypeDescription
accountFK → WhatsAppAccountThe WhatsApp account used to send this campaign
nameCharFieldHuman-readable campaign name
templateFK → WhatsAppTemplateThe approved template to send (must have status="APPROVED")
audience_typeCharField"contacts", "csv", or a named key from WHATSAPP["AUDIENCES"] in settings
audience_filtersJSONFieldExtra ORM filter kwargs applied when audience_type="contacts", e.g. {"labels__name": "vip"}
csv_fileFileFieldUploaded CSV when audience_type="csv"
parameter_mappingsJSONFieldMaps template variable index to a field name, e.g. {"1": "name", "2": "order_id"}
statusCharFielddraft, scheduled, running, completed, failed, or paused
scheduled_atDateTimeFieldOptional future datetime for a scheduled send
started_atDateTimeFieldTimestamp when the campaign began executing
completed_atDateTimeFieldTimestamp when the campaign finished executing
total_countPositiveIntegerFieldTotal audience size resolved at run time
sent_countPositiveIntegerFieldMessages accepted by Meta
delivered_countPositiveIntegerFieldDelivery confirmations received via webhook
read_countPositiveIntegerFieldRead receipts received via webhook
failed_countPositiveIntegerFieldMessages rejected by Meta or that errored

Creating a campaign

  1. Go to /whatsapp/campaigns/add/
  2. Select a template — only APPROVED templates appear (or all templates if none are approved yet)
  3. Choose an audience typecontacts, csv, or a named audience key from WHATSAPP["AUDIENCES"]
  4. Set parameter mappings — if your template contains {{1}}, {{2}} variables, map each index to a field on the audience object (e.g. {"1": "name"})
  5. Optionally schedule — leave scheduled_at blank to send immediately
  6. Save the campaign, then click Run to execute

Audience types

contacts — WhatsAppContact records

Queries all WhatsAppContact objects with opted_out=False and is_blocked=False. Apply additional ORM filters via audience_filters:
{"labels__name": "newsletter"}
This resolves each contact’s normalized_phone and display_name for the send.

csv — Uploaded file

Upload a CSV with at minimum a phone column. Any additional columns (e.g. name, order_id) are available for parameter_mappings.
phone,name,order_id
919876543210,Rahul Baberwal,ORD-999
911234567890,Priya Sharma,ORD-1001
10-digit numbers without a country code are automatically prefixed with 91 (India).

Named audiences — custom querysets

Register a callable in settings.py that returns a queryset or list:
# settings.py
WHATSAPP = {
    "AUDIENCES": {
        "premium_users": "myapp.audiences.get_premium_users",
    }
}
# myapp/audiences.py
from myapp.models import User

def get_premium_users():
    return User.objects.filter(plan="premium", is_active=True)
The PHONE_FIELD (default "phone") and NAME_FIELD (default "name") settings control which attributes are read from each object.

Running a campaign programmatically

from django_meta_whatsapp.utils import run_campaign, run_campaign_async

# Synchronous (blocks until complete — suitable for small audiences)
result = run_campaign(campaign_id=5)
print(f"Sent: {result['sent']}, Failed: {result['failed']}")

# Async via Celery (requires WHATSAPP_USE_CELERY = True)
result = run_campaign_async(campaign_id=5)
if result.get("queued"):
    print("Campaign queued for background execution")
run_campaign_async automatically falls back to synchronous execution if Celery is not configured, so it is safe to call in all environments.

Campaign analytics

Each campaign’s detail page at /whatsapp/campaigns/<pk>/ shows a live breakdown of:
  • Total — audience size at the time the campaign was run
  • Sent — accepted by Meta
  • Delivered — delivery confirmed by Meta webhook
  • Read — opened by the recipient
  • Failed — rejected by Meta or errored during send
The analytics dashboard at /whatsapp/analytics/ aggregates sent_count, delivered_count, read_count, and failed_count across all completed campaigns.

WhatsAppCampaignRecipient model

Every contact in the audience gets a WhatsAppCampaignRecipient row that tracks the per-recipient outcome:
FieldDescription
phone_numberRecipient phone number
nameResolved display name
parametersThe template variable values used for this recipient
statuspending, sent, delivered, read, or failed
message_idMeta message ID (wamid.*) returned on a successful send
error_messageError detail from Meta if the send failed
sent_atTimestamp of the successful API call
The first 100 recipients are shown in the campaign detail view, ordered by sent_at descending.
For large campaigns (thousands of contacts), enable Celery with WHATSAPP_USE_CELERY = True in settings. Without Celery, campaigns run synchronously in the web process and will time out for large audiences. See the Celery integration guide for setup instructions.
Only templates with status="APPROVED" can be used in campaigns. Sending to contacts with is_blocked=True or opted_out=True is automatically skipped by the audience resolver.

Build docs developers (and LLMs) love