← Back to blog
strategy·May 13, 2026·6 min read

ABM signals — how to fetch, process, and actually use intent data

A target account reads competitor reviews, visits your pricing page twice, and posts a job matching your solution. That's a buying signal most companies never see.

strategy

ABM signals — how to fetch, process, and actually use intent d…

A target account reads 5 reviews of your competitor on TrustRadius, visits your pricing page twice, and posts a job for the role that would use your product. That's not a lead. That's a buying signal. And most companies never see it.

Account-Based Marketing signals come from five different tools, none of which talk to each other. Your warehouse is where they converge into something actionable.

What ABM signals actually are

Three categories:

1. Buying intent signals

Direct indicators that a company is researching your category:

  • Review site activity — reading reviews on G2, TrustRadius, Capterra for products in your space
  • Content consumption — downloading whitepapers, attending webinars from you or competitors
  • Website visits — visiting your pricing page, case studies, comparison pages (via RB2B or similar)
  • Search behavior — searching for category terms, competitor names, solution keywords (from Bombora, G2 intent)

2. Tech-stack signals

Changes in a company's technology that indicate readiness to buy:

  • New tool adoption — switching from a competitor to a complementary tool (spotted via BuiltWith, HG Insights)
  • Tool removal — dropping a tool you replace (contract ending, tech-stack change)
  • Integration patterns — adopting tools that commonly pair with yours

3. Organizational signals

Company-level changes that create buying opportunities:

  • Hiring patterns — posting roles that would use your product (data engineers, RevOps, marketing ops)
  • Funding events — new round means new budget and new priorities
  • Leadership changes — new CTO, VP of Data, or CMO often triggers vendor evaluation
  • Expansion — new offices, new markets, growing headcount

The pipeline we built

For one client (SecureW2), we built the full signal-processing pipeline:

Clay (enrichment) ──→ Webhooks ──→ Cloud Function ──→ Pub/Sub ──→ BigQuery
TrustRadius ──→ API ──→ Cloud Function ──→ BigQuery
ZoomInfo intent ──→ API ──→ Cloud Function ──→ BigQuery
HG Insights ──→ CSV upload ──→ BigQuery
LinkedIn Jobs ──→ Scraper ──→ BigQuery
RB2B (web visitors) ──→ Webhook ──→ Cloud Function ──→ BigQuery
         │
         ▼
      dbt models (classify, score, route)
         │
         ▼
   Salesforce sync + Ad audience push + Slack alerts

Staging: normalize signals

-- models/staging/stg_signals__unified.sql
SELECT
    signal_id,
    account_domain,
    account_name,
    signal_type,        -- 'buying', 'tech', 'organizational'
    signal_source,      -- 'trustradius', 'zoominfo', 'rb2b', 'linkedin_jobs', 'clay'
    signal_detail,      -- human-readable description
    signal_strength,    -- raw score from source (normalized 0-100)
    detected_at,
    raw_payload
FROM {{ source('signals', 'raw_buying_signals') }}
 
UNION ALL
 
SELECT
    signal_id,
    account_domain,
    account_name,
    'tech' AS signal_type,
    'hg_insights' AS signal_source,
    CONCAT('Adopted ', technology_name) AS signal_detail,
    80 AS signal_strength,  -- tech adoption is a strong signal
    detected_at,
    raw_payload
FROM {{ source('signals', 'raw_tech_signals') }}
 
UNION ALL
 
SELECT
    signal_id,
    account_domain,
    account_name,
    'organizational' AS signal_type,
    'linkedin_jobs' AS signal_source,
    CONCAT('Hiring: ', job_title) AS signal_detail,
    CASE
        WHEN LOWER(job_title) LIKE '%head of data%' THEN 90
        WHEN LOWER(job_title) LIKE '%data engineer%' THEN 70
        WHEN LOWER(job_title) LIKE '%analytics%' THEN 60
        ELSE 40
    END AS signal_strength,
    posted_date AS detected_at,
    raw_payload
FROM {{ source('signals', 'raw_job_signals') }}

Scoring: aggregate per account

Individual signals are weak. Aggregated signals per account are strong.

-- models/intermediate/int_signals__account_score.sql
SELECT
    account_domain,
    account_name,
    COUNT(*) AS total_signals,
    COUNT(DISTINCT signal_type) AS signal_diversity,
    SUM(signal_strength) AS raw_score,
    MAX(detected_at) AS most_recent_signal,
    -- Weighted score: more signal types = higher confidence
    SUM(signal_strength) * (1 + 0.2 * COUNT(DISTINCT signal_type)) AS weighted_score,
    -- Time decay: recent signals matter more
    SUM(
        signal_strength * EXP(-0.1 * DATE_DIFF(CURRENT_DATE, DATE(detected_at), DAY))
    ) AS decayed_score,
    ARRAY_AGG(STRUCT(signal_type, signal_source, signal_detail, detected_at)
              ORDER BY detected_at DESC LIMIT 5) AS recent_signals
FROM {{ ref('stg_signals__unified') }}
WHERE detected_at >= CURRENT_DATE - 90  -- 90-day lookback
GROUP BY 1, 2

Routing: threshold → action

-- models/marts/mart_signal_routing.sql
SELECT
    s.account_domain,
    s.account_name,
    s.decayed_score,
    s.total_signals,
    s.recent_signals,
    -- Check CRM status
    sf.account_id AS salesforce_account_id,
    sf.account_owner,
    sf.account_stage,
    -- Route decision
    CASE
        WHEN sf.account_id IS NOT NULL AND sf.account_stage = 'Customer'
        THEN 'UPSELL_ALERT'           -- existing customer showing new signals
        WHEN sf.account_id IS NOT NULL AND sf.account_stage IN ('Prospect', 'Qualified')
        THEN 'ACCELERATE'             -- known prospect with rising intent
        WHEN s.decayed_score > 200
        THEN 'NEW_HIGH_INTENT'        -- unknown account, strong signals
        WHEN s.decayed_score > 100
        THEN 'ADD_TO_NURTURE'         -- warm enough for ad audience
        ELSE 'MONITOR'
    END AS routing_action
FROM {{ ref('int_signals__account_score') }} s
LEFT JOIN {{ ref('stg_salesforce__accounts') }} sf
    ON s.account_domain = sf.website_domain

Activation

The routing model feeds three outputs:

  1. Salesforce sync (via Hightouch) — create or update accounts, attach signals as activities, assign to the right owner
  2. Ad audience push — accounts scoring above threshold get added to LinkedIn and Google Ads matched audiences for retargeting
  3. Slack alerts — high-intent signals from named accounts get pushed to a #signals channel with context

The scoring philosophy

Signal scoring is an art, not a science. Our approach:

  • Start simple. Binary thresholds first (above/below). Add nuance later.
  • Weight by signal type. A pricing page visit (buying intent) matters more than a job posting (organizational). A TrustRadius competitor review (buying intent + competitive) matters most.
  • Require signal diversity. One signal from one source is noise. Three signals from three sources is a pattern. The signal_diversity multiplier handles this.
  • Decay over time. A signal from last week matters. A signal from 4 months ago doesn't. Exponential decay ensures the score reflects current intent, not historical activity.
  • Validate against closed deals. After 3 months, compare signal scores at the time of deal creation against win rates. Adjust weights based on what actually predicts revenue.

What most teams get wrong

1. Buying a tool instead of building a pipeline

6sense, Demandbase, and Bombora are expensive and opaque. They give you a score and a tier. They don't show you the underlying signals, and you can't customize the scoring for your specific ICP.

A warehouse-native approach costs less, gives you full transparency, and lets you iterate on the scoring model weekly.

2. Treating all signals equally

A website visit is not the same as a competitor review. Weight accordingly.

3. No CRM integration

Signals that don't reach the sales team don't generate revenue. The pipeline must end in Salesforce (or whatever CRM you use), with signals attached to accounts and routed to owners.

The payoff

Before the pipeline: sales reps research accounts manually, check LinkedIn sporadically, and rely on inbound to tell them who's interested.

After: a Slack message arrives — "Acme Corp (500 employees, $2M ARR target) scored 280 this week. Signals: visited pricing page 3x, posted 2 data-engineer roles, reviewed Competitor X on TrustRadius. Routed to: @sales-rep."

That's the difference between waiting for a lead and knowing who's ready to buy.


We built this exact pipeline for a B2B SaaS company — from Clay webhooks to BigQuery to Salesforce sync. If your sales team is still guessing which accounts are in-market, book a discovery call and we'll show you what signal-driven outreach looks like.

Got a similar problem?

30 minutes. We'll tell you honestlywhat's broken.