Skip to main content
WhatsApp Guides

WhatsApp Interactive Message Button Analytics: AWS Kinesis Data Firehose Setup

Anita Singh
11 min read
Views 5
Featured image for WhatsApp Interactive Message Button Analytics: AWS Kinesis Data Firehose Setup

The Latency Problem in WhatsApp Interaction Tracking

Standard analytics implementations rely on synchronous webhook listeners. When a user clicks an interactive button in WhatsApp, the platform sends a POST request to your server. Processing these requests in real time works for small volumes. As traffic scales, your database connections saturate. Response latency increases. You lose data during peak campaign hours.

Tracking WhatsApp interactive message button analytics requires a decoupled architecture. You need a system that accepts incoming data immediately and buffers it for downstream processing. Amazon Kinesis Data Firehose serves this purpose by providing a managed service to stream data directly into storage or analytical tools. This approach ensures your webhook listener remains responsive while your data team gains a durable record of every user interaction.

Why Kinesis Data Firehose for Button Events

Kinesis Data Firehose simplifies the ingestion pipeline. It handles batching, compression, and data transformation without requiring you to manage individual servers. For WhatsApp marketing teams, this means the ability to track click-through rates (CTR) and conversion funnels across millions of messages without infrastructure overhead.

Firehose integrates with Amazon S3 for long-term storage and Amazon Athena for SQL-based analysis. You avoid the high costs of keeping raw logs in a transactional database like PostgreSQL or MySQL. Instead, you store compressed Parquet or JSON files in S3 and pay only for the data you query.

Prerequisites for the Implementation

Before starting the setup, ensure you have the following components ready:

  1. An AWS Account with permissions for Kinesis, Lambda, and S3.
  2. A WhatsApp Business API account or a WASenderApi session for sending interactive messages.
  3. A public webhook endpoint (using AWS Lambda and API Gateway or a dedicated Node.js server).
  4. An S3 bucket designated for analytics storage.

If you use WASenderApi, your webhook configuration will capture the message event. The system identifies button clicks through specific payload keys. Verify your session is active and the webhook URL is correctly registered in the dashboard.

Step 1: Create the Kinesis Data Firehose Delivery Stream

Log in to the AWS Management Console and navigate to Kinesis. Select Data Firehose and click Create delivery stream.

  1. Source: Choose "Direct PUT". This allows your webhook listener to send data to the stream via the AWS SDK.
  2. Destination: Select Amazon S3.
  3. Delivery stream name: Assign a descriptive name such as whatsapp-button-analytics-stream.
  4. Buffering hints: Set the buffer size to 5 MB and the buffer interval to 60 seconds. This optimizes costs by reducing the number of small files written to S3.
  5. Compression and encryption: Enable GZIP compression to save on storage costs.

Step 2: Configure the Webhook Listener

Your webhook listener must extract the relevant button interaction data and forward it to Kinesis. The following example uses Node.js with the AWS SDK to push data to the stream.

const { FirehoseClient, PutRecordCommand } = require("@aws-sdk/client-firehose");
const firehoseClient = new FirehoseClient({ region: "us-east-1" });

exports.handler = async (event) => {
  const body = JSON.parse(event.body);

  // Identify if the message is a button reply
  if (body.entry && body.entry[0].changes[0].value.messages) {
    const message = body.entry[0].changes[0].value.messages[0];

    if (message.type === 'interactive' && message.interactive.button_reply) {
      const analyticsData = {
        timestamp: new Date().toISOString(),
        wa_id: message.from,
        button_id: message.interactive.button_reply.id,
        button_text: message.interactive.button_reply.title,
        context_id: message.context ? message.context.id : null
      };

      const params = {
        DeliveryStreamName: "whatsapp-button-analytics-stream",
        Record: {
          Data: Buffer.from(JSON.stringify(analyticsData) + "\n")
        }
      };

      try {
        await firehoseClient.send(new PutRecordCommand(params));
      } catch (err) {
        console.error("Error sending to Firehose:", err);
      }
    }
  }

  return {
    statusCode: 200,
    body: JSON.stringify({ status: "received" }),
  };
};

Step 3: Map the Data Schema

When WhatsApp sends an interactive button response, the payload contains nested objects. Your analytics pipeline must normalize this data. If you use the official API, the JSON structure follows the Meta developer documentation. If you use WASenderApi, the payload structure remains consistent with the message types defined in their documentation.

Below is a sample of the raw JSON payload you will receive from a button click:

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
      "changes": [
        {
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "123456789",
              "phone_number_id": "PHONE_NUMBER_ID"
            },
            "messages": [
              {
                "context": {
                  "from": "123456789",
                  "id": "wamid.HBgLMTIzNDU2Nzg5ORUCABEYEjA0REExQjYyQjU0OUEzN0ExNwA="
                },
                "from": "987654321",
                "id": "wamid.HBgLMTIzNDU2Nzg5ORUCABEYEjdDMUUzNjU1QjZFQkU0M0VBQwA=",
                "timestamp": "1678901234",
                "type": "interactive",
                "interactive": {
                  "type": "button_reply",
                  "button_reply": {
                    "id": "offer_accept_001",
                    "title": "Accept Offer"
                  }
                }
              }
            ]
          },
          "field": "messages"
        }
      ]
    }
  ]
}

Step 4: Data Transformation with Lambda

Raw JSON from webhooks often contains unnecessary metadata. Firehose allows you to invoke an AWS Lambda function for data transformation before the data reaches S3. This step is useful for flattening the structure. Flattening makes it easier for Amazon Athena to read the files without complex nested queries. Use the Lambda function to extract only the button_id, wa_id, and timestamp fields.

Step 5: Analyzing Button Performance with SQL

Once the data arrives in S3, use Amazon Athena to run queries. First, create a table that points to your S3 folder. Then, you can calculate the performance of specific buttons. This data reveals which calls-to-action (CTAs) drive the most engagement.

SELECT
    button_id,
    button_text,
    COUNT(*) as total_clicks,
    COUNT(DISTINCT wa_id) as unique_users
FROM
    whatsapp_analytics.button_clicks
WHERE
    timestamp > '2023-10-01T00:00:00Z'
GROUP BY
    button_id,
    button_text
ORDER BY
    total_clicks DESC;

Managing Edge Cases in Analytics Pipelines

Tracking WhatsApp interactions introduces specific edge cases that impact data accuracy. Addressing these ensures your reports reflect actual user behavior.

Duplicate Webhook Events

WhatsApp sometimes sends duplicate webhooks if your server takes too long to respond. The wamid is the unique message identifier. When processing clicks, your transformation logic should include the wamid. You can then filter for duplicates in Athena using DISTINCT or a GROUP BY clause. This prevents artificial inflation of your click metrics.

Timezone Offsets

WhatsApp timestamps are in Unix epoch format. AWS Kinesis uses ISO 8601 for its internal logging. Ensure your SQL queries convert Unix timestamps to your reporting timezone. Failure to align timezones results in data spikes that do not match your campaign launch times.

Interactive Button Types

WhatsApp supports multiple interactive types including button_reply, list_reply, and flow responses. Your webhook listener logic must distinguish between these. If you only track button_reply, you will miss data from list selections or flow form submissions. Update your ingestion logic to check the type field in the message object and capture all relevant interaction keys.

Troubleshooting the Firehose Pipeline

If data is not appearing in your S3 bucket, check these common points of failure:

  • IAM Role Permissions: The role assigned to Kinesis Firehose must have s3:PutObject and s3:GetBucketLocation permissions for the destination bucket.
  • Lambda Timeout: If using a transformation function, ensure the timeout is sufficient. Large batches of records require more processing time. Set the timeout to at least 1 minute.
  • Firehose Buffering: Data does not appear in S3 immediately. It waits until the buffer size or time limit is reached. If you are testing with single clicks, you must wait for the buffer interval (e.g., 60 seconds) to see the file.
  • Webhook 5xx Errors: If your webhook listener fails to respond within 10 seconds, WhatsApp retries the delivery. Ensure your code sends the 200 OK status before starting heavy processing or use an asynchronous queue.

Frequently Asked Questions

How much does it cost to run this analytics pipeline?

Kinesis Data Firehose charges based on the volume of data processed. For most WhatsApp campaigns, the cost is minimal because text payloads are small. S3 storage costs are also low for compressed files. Amazon Athena charges $5 per terabyte of data scanned. By partitioning your data by date in S3, you keep query costs extremely low.

Is it possible to track button clicks without using AWS?

You can use other cloud providers like Google Cloud Dataflow or Azure Stream Analytics. The principle remains the same. You need a streaming service to buffer the data. If you use a single database, you risk performance bottlenecks during high-traffic events.

Does this track clicks if the user is offline?

WhatsApp messages are delivered when the user comes online. The interaction only occurs when the user views the message and clicks a button. The timestamp in the webhook reflects when the click happened on the user's device. This allows for accurate time-series analysis regardless of when your server receives the data.

Can I use this setup with WASenderApi?

Yes. WASenderApi provides webhooks for all incoming messages. You must parse the webhook JSON to find the interactive response keys. The Kinesis Data Firehose logic remains identical. You simply adapt the transformation function to match the WASenderApi payload format.

How do I join button clicks with my internal user database?

The wa_id or phone number serves as the primary key. You can export your S3 data to your main database or use Athena Federated Query to join S3 data with an RDS or DynamoDB instance. This allows you to see which specific customer segments are interacting with your buttons.

Next Steps for Data Analysis

Building the pipeline is the first stage. Once your data flows into S3, focus on creating dashboards. Use Amazon QuickSight or a similar visualization tool to monitor CTR in real time. Look for patterns in response times. Analyze which button positions (first, second, or third) receive the most clicks. These engineering insights allow your marketing team to refine message templates based on telemetry rather than assumptions.

Share this guide

Share it on social media or copy the article URL to send it anywhere.

Use the share buttons or copy the article URL. Link copied to clipboard. Could not copy the link. Please try again.