Portfolio project ยท automated pipeline, runs every 4 hours

GTM Signal Engine

A go-to-market signal detection system that scores B2B SaaS accounts from product usage data and routes the ones worth calling straight into HubSpot and Telegram, built on BigQuery SQL and n8n.

25
critical accounts
19
hot accounts
44
accounts flagged
Next automated check in ...

The problem

Sales teams waste time guessing which accounts are ready to expand. The data that answers that question already sits in the product's usage logs, but nobody looks at it, because nobody built the pipeline that would surface it. This project is that pipeline, built end to end: SQL scoring, workflow automation, CRM sync, and real-time alerts.

Proof it's live

This isn't a static mockup. The scheduler below fires on its own every four hours, and this is a real alert it sent to Telegram, unedited.

GE
GTM Signal Engine
Telegram bot ยท sent automatically by n8n
AUTOMATED
๐Ÿ“Š GTM SIGNAL ENGINE REPORT Thursday, 29 October 2026 at 07:24 am โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” ๐Ÿ“ˆ Total accounts flagged: 44 ๐Ÿ”ด Critical (85+): 25 ๐ŸŸ  Hot (70-84): 19 ๐ŸŸก Warm (50-69): 0 โ”โ” CRITICAL โ”โ”โ”โ”โ”โ”โ”โ”โ” โ€ข PlayFlow: 100 | usage spike + seat crunch + feature milestone โ€ข Johnson Technologies: 100 | usage spike + seat crunch + feature milestone โ€ข Hill Technologies: 100 | usage spike + seat crunch + feature milestone ...and 22 more โ”โ” HOT โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” โ€ข Baldwin Technologies: 78 | usage spike + feature milestone โ€ข SongStack: 72 | seat crunch + feature milestone ...and 17 more โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” โœ… 44 contacts synced to HubSpot โฐ Next check in 4 hours
Sent via n8n โ†’ Telegram Bot API Every 4 hours, unattended

How scoring works

Every account is checked daily against three expansion signals. Each signal carries a weight, and accounts triggering more than one get a multiplier, so a company showing every sign of being ready to buy rises straight to the top of the list.

40 pts Usage spikeDaily active users exceed 2x the 7-day rolling average AVG() OVER
35 pts Seat crunchMore than 80% of purchased seats are in active use SAFE_DIVIDE()
25 pts Feature milestoneThe account has adopted 10 or more product features MAX() OVER
Critical, 85+ (25 accounts) Hot, 70โ€“84 (19 accounts) Warm, 50โ€“69 (0 accounts) Cold, under 50

The SQL

The scoring logic is a single BigQuery view built from three stacked queries: rolling averages, signal detection, and composite scoring. Here's the core of it.

sql/03_composite_scoring.sql
-- 7-day rolling average of daily active users, per company
AVG(daily_active_users) OVER (
    PARTITION BY company_id
    ORDER BY event_date
    ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS dau_7d_avg,

-- Usage spike: today's DAU is more than 2x the rolling average
(dau_7d_avg > 0 AND daily_active_users > dau_7d_avg * 2) AS has_usage_spike,

-- Seat crunch: utilization above 80 percent
(SAFE_DIVIDE(seats_used, seats_purchased) * 100 > 80) AS has_seat_crunch,

-- Feature milestone: cumulative adoption hits 10+ features
(MAX(features_used) OVER (
    PARTITION BY company_id
    ORDER BY event_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) >= 10) AS has_feature_milestone,

-- Weighted base score, then a multiplier for accounts firing
-- more than one signal at once
(CASE WHEN has_usage_spike THEN 40 ELSE 0 END)
+ (CASE WHEN has_seat_crunch THEN 35 ELSE 0 END)
+ (CASE WHEN has_feature_milestone THEN 25 ELSE 0 END) AS base_score,

CASE
    WHEN signals_firing >= 3 THEN 1.3
    WHEN signals_firing = 2 THEN 1.2
    ELSE 1.0
END AS multiplier,

LEAST(100, ROUND(base_score * multiplier)) AS signal_score

Architecture

One BigQuery view feeds three independent consumers: an n8n workflow that syncs CRITICAL and HOT accounts to HubSpot and sends Telegram alerts every four hours, an auto-synced Google Sheets export, and this live dashboard.

Python generator 75 companies ยท 90 days BigQuery usage_events table SQL: scored_signals view Window functions ยท CTEs ยท composite scoring Rolling averages โ†’ signal flags โ†’ 0โ€“100 score n8n workflow Every 4 hours Google Sheets Auto-synced via n8n Looker Studio This dashboard HubSpot CRM upsert Telegram Signal alerts

Live dashboard

Filter by tier or plan, sort the account table by score, and see exactly which companies the system is flagging right now.

Try it yourself

Download the sample dataset, upload it to a free BigQuery Sandbox project, and run the scoring view yourself. No billing account required.

Built with

ComponentCost
Data warehouseBigQuery SandboxFree
Scoring logicBigQuery SQLFree
Data generationPython + Faker + PandasFree
Orchestrationn8n, self-hosted$6/mo
CRMHubSpot FreeFree
AlertsTelegram Bot APIFree
DashboardLooker Studio + SheetsFree