Data Sources → Customer Touchpoints

Email / SMS

Outbound and inbound engagement on email and SMS channels — opens, clicks, replies, and opt-outs — usually reported back by the sending platform.

High-Level Design

ESP webhook → .NET Core microservices on Azure.

Touchpoint
Email / SMS
Outbound campaigns, inbound replies
→
Ingestion
Azure Function (Webhook Receiver)
SendGrid/Twilio webhook → Cxos.Ingestion.Client
→
Processing
.NET Core Stream Worker
Priority path for opt-outs via Azure Event Hubs
→
Foundation
Data Lakehouse
Engagement history per profile
→
Intelligence
.NET Core Analytics API
Azure DB for PostgreSQL — campaign performance
→
Activation
.NET Core Activation API
Next-best-channel, suppression sync (Reverse ETL)

💼 Business Context

  • Email/SMS engagement is a leading indicator of campaign ROI and channel fatigue
  • Opt-out/consent events here are legally load-bearing — mishandling them creates compliance risk
  • Owned by Lifecycle/CRM Marketing; consent state is shared with Legal/Compliance

🔌 Technical Overview

SendGrid and Twilio call a .NET Core Azure Function webhook endpoint for every engagement event (send, open, click, bounce, opt-out); the function validates the provider signature and forwards the event through Cxos.Ingestion.Client into the Ingestion API. The Stream Worker routes two priority tiers onto separate Azure Event Hubs consumer groups: standard engagement (opens/clicks) and compliance-critical (unsubscribes/bounces), so opt-outs are never queued behind bulk analytics traffic. The Analytics API (ASP.NET Core + Dapper) reads rollups from Azure Database for PostgreSQL Flexible Server for campaign dashboards.

Typical Events

email_sent email_opened email_clicked sms_delivered unsubscribed

💾 Sample Event Payload

{
  "event": "email_clicked",
  "event_id": "1e438f2b-3a9c-4c2d-8b1a-6f2e0d4a7c93",
  "timestamp": "2026-08-01T08:15:47Z",
  "user_id": "cust_004821",
  "context": {
    "channel": "email",
    "campaign_id": "camp_2291",
    "provider": "sendgrid"
  },
  "properties": {
    "link_url": "/summer-sale",
    "message_id": "msg_774f"
  }
}

🔗 Integration Points

  • Azure Function webhook receivers for SendGrid / Twilio / Braze
  • Cxos.Ingestion.Client NuGet package — shared contract for the outbound call into the Ingestion API
  • Azure Event Hubs — dual consumer groups (standard vs. compliance-priority)
  • Reverse ETL (.NET Core Activation API + Azure Functions) — suppression list sync back to the ESP

🧰 Services Consumed

  • Owning microservice — Cxos.Ingestion.Api (see the Full Application Service Map)
  • Database — Azure Cache for Redis (cache only, no system-of-record database)

⚠️ Non-Functional Considerations

  • Scale: campaign sends can generate millions of webhook callbacks in a short burst — Azure Functions consumption plan scales out automatically
  • Latency: opt-out events are applied within minutes via the compliance-priority Event Hubs consumer group
  • Reliability: webhook handling is idempotent (event_id dedup) since providers frequently retry deliveries
  • Security/Privacy: consent state is written to an auditable table in Azure Database for PostgreSQL, not just a marketing flag

🎯 Enterprise Example

A retail brand's promotional SMS blast generates an unsubscribe spike within 5 minutes. Because the Azure Function webhook receiver routes opt-out events onto the compliance-priority Event Hubs consumer group, every affected contact is suppressed from the next wave of the same campaign before it sends — avoiding a compliance incident and an estimated $40K in regulatory exposure.

← Back to Customer Touchpoints