How to calculate conversion rate by channel in Real-Time Analytics
Calculating conversion rate by channel in Real-Time Analytics lets you see, in real time, which channels (e.g.: email, ads, organic) convert better and act quickly. This tutorial explains why and shows how to build a simple ingestion pipeline, windowed aggregation and calculation of conversion rate by channel.
Prerequisites
- Account on an event-streaming service (e.g.: Apache Kafka, Event Hubs)
- Real-time processing system (e.g.: Azure Stream Analytics, Apache Flink or Spark Structured Streaming)
- Storage for results (e.g.: Azure SQL, Cosmos DB, or an output Kafka topic)
- Event data with fields: event_time, user_id, channel, event_type (e.g.: page_view, purchase)
Step 1: Understand the metric and required events
Conversion rate by channel = (no. of users with a conversion event in a channel) / (no. of users exposed or visitors in a channel) within a time window. We need to distinguish exposure/visit events (e.g.: page_view) from conversion events (e.g.: purchase). Use user_id to avoid duplicates per user.
Step 2: Model the time window and granularity
Choose tumbling or sliding window (e.g.: 1-minute tumbling for real-time dashboards). Granularity defines update frequency and cost. For getting started, use a 1-minute tumbling window per channel.
Step 3: Example with Azure Stream Analytics (SQL-like query)
Practical example using Azure Stream Analytics to count unique users per channel and calculate conversion rate in a 1-minute tumbling window. The source is an Event Hub with JSON events.
-- Contagem de visitantes únicos por canal (page_view)
SELECT
System.Timestamp() AS window_end,
channel,
COUNT(DISTINCT user_id) AS visitors
INTO
output_visitors
FROM
input_events
WHERE
event_type = 'page_view'
GROUP BY
TumblingWindow(minute, 1), channel;
-- Contagem de conversões únicas por canal (purchase)
SELECT
System.Timestamp() AS window_end,
channel,
COUNT(DISTINCT user_id) AS conversions
INTO
output_conversions
FROM
input_events
WHERE
event_type = 'purchase'
GROUP BY
TumblingWindow(minute, 1), channel;
-- Juntar resultados e calcular taxa de conversão (pode ser feito numa query separada ou em downstream)
Step 4: Join results and calculate conversion rate
If the engine does not support joining outputs, persist both outputs to storage and then run a query that joins by window_end and channel. SQL example for a destination like Azure SQL or a job that combines the outputs:
SELECT
v.window_end,
v.channel,
v.visitors,
c.conversions,
CASE WHEN v.visitors = 0 THEN 0 ELSE CAST(c.conversions AS FLOAT)/v.visitors END AS conversion_rate
FROM
visitors_table v
LEFT JOIN
conversions_table c
ON
v.window_end = c.window_end AND v.channel = c.channel
ORDER BY v.window_end DESC;
Step 5: Handle duplicates and short sessions (best practices)
Use COUNT(DISTINCT user_id) to avoid duplicates within the window. To prevent inflated counts from bots, filter suspicious user_agents or create heuristics (e.g.: events with very short duration). If the platform allows, apply deduplication by event_id before aggregation.
Step 6: Visualize in real time and configure alerts
Send the resulting table to a destination supported by your dashboard (e.g.: Power BI DirectQuery, or Cosmos DB + Azure Synapse). Configure alerts when conversion_rate falls below a threshold or when visitors/conversions show abrupt changes.
Verify the result
Confirm that for each 1-minute window there is one row per channel with visitors, conversions and conversion_rate between 0 and 1. Test with sample events: sending 10 page_view and 2 purchase in the same channel should show visitors≥10 (depending on user_id) and the corresponding conversion_rate. Check Stream Analytics logs for common errors (schema mismatch, out-of-order timestamps).
Conclusion
With a tumbling window and distinct counts by user_id it is straightforward to obtain conversion rate by channel in Real-Time Analytics. Next steps: try sliding windows, normalize by sessions and integrate anti-fraud filters. Tip: start with larger windows to validate logic before reducing for lower latency.