About GridPulse CRM

Internal campaign intelligence for Tibber's CRM operations

GridPulse CRM

v1.0 · Internal Tool · Tibber CRM Team

GridPulse is Tibber's internal campaign intelligence dashboard. It connects to Braze to sync campaign and Canvas metadata, ingests Currents messaging events, detects message overlaps and conflicts, and surfaces everything in a dashboard with per-user journey timeline views. The goal is to give the CRM team full visibility into what each customer actually experiences across all campaigns — and to catch problems before they cause churn, unsubscribes, or spam complaints.

What GridPulse Does

Campaign Sync

Pulls all active campaigns and Canvases from Braze via cron, including tag-based classification (journey stage, intent, CTA category, team owner).

Event Ingestion

Ingests Braze Currents events (sends, opens, clicks, bounces, spam) via R2, normalises them into a unified schema enriched with campaign metadata.

Conflict Detection

A pluggable rule engine evaluates per-user event streams and generates alerts when anti-patterns are detected — timing floods, competing CTAs, dead zones, and more.

Dashboard & Insights

Visual dashboards covering KPIs, journey timelines, lifecycle analysis, heatmaps, collision maps, dead zones, and a conflict resolution workflow.

Conflict Detection Rules

GridPulse runs 7 configurable rules against per-user event streams. Each rule generates alerts with severity levels and suggested fixes. Thresholds and windows are tuneable via the Rules page.

RuleWhat It CatchesSeverity
Timing Flood3+ messages within 24 hoursHigh
Channel Flood3+ messages on the same channel within 48 hoursHigh
Discount Before SalesDiscount CTA sent shortly before a sales-intent campaignHigh
Competing CTAsMessages with 2+ different CTAs within 24 hoursMedium
Onboarding Dead Zone3+ day communication gap during first 14 daysMedium
Post-Spam SendMessage sent to a user who reported spam within 7 daysCritical
Re-onboarding ActiveActive user (30+ days) enrolled into onboarding journeyLow

Architecture

Braze REST API ──(cron)──> Worker ──> D1 (campaigns, canvas_steps)
Braze Currents ──> R2 ──(cron)──> Worker ──> D1 (unified_events)
                                      │
                                      ├──> Queue ──> Conflict Detector ──> D1 (alerts)
                                      │
SvelteKit (Pages) <──── API routes <──┘
Workers
API + Cron
D1
SQLite Database
R2
Object Storage
Queues
Async Processing

Build Roadmap

Phase 1 — Foundation
Project scaffold, D1 schema, Braze API client, campaign sync, tag parser, rule engine with 7 rules, dashboard + campaign table + conflict feed.
COMPLETE
Phase 2 — Currents Ingestion
R2 Currents file parser, ingestion cron with cursor tracking, user daily summaries, overlap alert generation, live timeline + trend data.
PLANNED
Phase 3 — Conflict Detection Pipeline
Queue-based detection, live rule execution, campaign pair stats, heatmap visualisation, conflict resolution workflow.
UPCOMING
Phase 4 — Polish & Alerts
Slack/webhook notifications, data retention cleanup, date range pickers, export functionality, rule parameter tuning UI.
UPCOMING
Phase 5 — Hardening
Error handling, monitoring, documentation, load testing with production-scale data, Cloudflare Access fine-tuning.
UPCOMING

Why GridPulse Exists

As Tibber's CRM programme scales — more campaigns, more markets, more channels — the risk of campaigns interfering with each other grows. Braze provides excellent campaign execution, but it lacks retrospective intelligence about cross-campaign customer experience. GridPulse fills that gap:

Visibility

See the full picture of what each customer receives across all campaigns, channels, and teams — not just individual campaign performance.

Detection

Automatically catch anti-patterns — message floods, competing CTAs, dead zones — that erode customer trust and drive unsubscribes.

Coordination

Give CRM teams across markets and functions a shared operational view, replacing tribal knowledge with data-driven conflict resolution.

Tech Stack

Runtime Cloudflare Workers
Database Cloudflare D1 (SQLite)
Object Storage Cloudflare R2
Async Processing Cloudflare Queues
Frontend SvelteKit + Tailwind CSS
Hosting Cloudflare Pages
Data Source Braze REST API + Currents

Access & Security

Live Mode Authentication

Live Braze data is password-protected. The password is never stored in the client — only a SHA-256 hash is shipped in the bundle. The hash also serves as a Bearer token for server-side API validation.

Session-Based Unlock

Unlock state is stored in sessionStorage — it resets when you close the tab or browser. Each new session starts locked to mock data by default.

Rate Limiting

After 5 failed password attempts, the input is locked for 30 seconds to prevent brute-force attacks.

Server-Side Enforcement

API requests for live data require a valid Bearer token. Requests without the token receive a 401 Unauthorized response — preventing direct curl access to production Braze data.

CORS Policy

The API only accepts requests from the deployed Pages domain and localhost development servers. Cross-origin requests from other domains are rejected.

Data Sensitivity

Contains anonymised external user IDs and campaign metadata. No PII is stored directly.

Contact

CRM Operations Team — reach out on Slack for questions, feedback, or access requests.