DEV Community

Cover image for Stop Blasting Cold Emails: Build an Intent-Triggered Outreach Engine Instead
Michael
Michael

Posted on Originally published at getmichaelai.com

Stop Blasting Cold Emails: Build an Intent-Triggered Outreach Engine Instead

Most B2B outreach fails for one boring reason: timing. You send a perfect email to a perfect prospect who has zero reason to care today. The message isn't wrong. The moment is.

Intent-based outreach flips this. Instead of a fixed cadence firing at everyone on a list, you wait for a signal - then trigger a personalized message within minutes. This is very buildable with tools you probably already have. Here's the architecture.

What Counts as a Buyer Intent Signal

Intent data is anything that suggests a prospect is actively evaluating a solution. It falls into two buckets:

First-party signals happen on your own properties:

  • Pricing page visits (especially repeat visits)
  • Docs or integration page views
  • Free trial signups that stall
  • Demo form abandons

Third-party signals happen off your site:

  • Job postings mentioning tools you complement
  • Funding announcements
  • New hires in relevant roles (a new Head of RevOps is a buying committee forming)
  • Technographic changes (they just installed a competitor's tag)

The strongest triggers combine both. A prospect who visits your pricing page and just posted a job for the exact problem you solve is a green light.

The Core Loop

Every intent engine has the same shape:

  1. Capture a signal
  2. Enrich the account and contact
  3. Score whether it's worth acting on
  4. Generate a personalized message grounded in the signal
  5. Route it - to a rep or an automated send

Miss any step and quality collapses. Skip enrichment and your AI writes generic copy. Skip scoring and you spam every tire-kicker.

Capturing the Signal

Start with what's free. A simple script on your pricing page tells you more than most paid intent vendors.

// Track high-intent page views and push to your automation webhook
async function trackIntent(pageType) {
  const visitorId = getVisitorId(); // from your cookie / analytics
  const account = await identifyAccount(visitorId); // reverse-IP or Clearbit

  if (!account?.domain) return;

  await fetch('https://your-n8n-instance/webhook/intent', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      domain: account.domain,
      page: pageType,
      timestamp: Date.now(),
      sessionCount: account.sessions
    })
  });
}

// Fire on the pages that actually indicate buying intent
if (window.location.pathname.includes('/pricing')) {
  trackIntent('pricing');
}
Enter fullscreen mode Exit fullscreen mode

Scoring Before You Act

Don't let one page view trigger an email. Weight signals and set a threshold. A pricing visit is worth more than a blog read. A repeat pricing visit within 48 hours is worth a lot more.

SIGNAL_WEIGHTS = {
    "pricing_view": 30,
    "pricing_repeat": 50,
    "docs_view": 20,
    "demo_abandon": 45,
    "job_post_match": 40,
    "recent_funding": 25,
}

def score_account(signals: list[str]) -> int:
    return sum(SIGNAL_WEIGHTS.get(s, 0) for s in signals)

def should_trigger(signals: list[str], threshold: int = 60) -> bool:
    score = score_account(signals)
    return score >= threshold

# Example
signals = ["pricing_repeat", "job_post_match"]
print(score_account(signals))      # 90
print(should_trigger(signals))     # True
Enter fullscreen mode Exit fullscreen mode

The threshold is a dial. Set it high early, then loosen it as you trust the pipeline.

Where AI Actually Earns Its Keep

The AI's job is not to invent a persona or fabricate flattery. It's to write a message that references the specific signal in a way a human would.

Feed the model the raw context - the signal, the enriched account data, the role - and constrain it hard.

prompt = f"""
Write a 3-sentence outreach email.

Context:
- Company: {account['name']} ({account['industry']})
- Signal: visited pricing page twice in 48h, recently posted a
  job for a RevOps Manager
- Recipient role: VP of Sales

Rules:
- Reference the RevOps hire naturally, not the page visit
  (that's creepy).
- No superlatives, no 'I hope this finds you well'.
- One clear, low-friction ask.
"""
Enter fullscreen mode Exit fullscreen mode

Notice the guardrail: reference the public signal (the job post), not the private one (their browsing). Using the browsing signal to time the send is smart. Mentioning it in the copy is a trust-killer.

Route, Don't Auto-Send Everything

High-score accounts should go to a human with a pre-drafted message and full context. Mid-score accounts can enter a lighter automated sequence. This tiering keeps your best prospects in front of your best closers while automation handles volume.

A simple rule set:

  • Score 80+ → Slack alert to the account owner with draft ready
  • Score 60-79 → Automated 3-touch sequence
  • Below 60 → Nurture, no direct outreach

Build This in Stages

Don't try to boil the ocean. A realistic first quarter:

  1. Week 1-2: Instrument your pricing and docs pages. Pipe events to a webhook.
  2. Week 3-4: Add enrichment and a basic scoring threshold.
  3. Week 5-6: Wire up AI drafting with strict prompts and human review.
  4. Week 7+: Layer in a third-party signal source, then start automating the mid-tier.

The teams winning at outbound right now aren't sending more. They're sending at the right moment, with context that proves they were paying attention. That's not a bigger list. It's a better trigger.

Start with one signal, one message template, and one human in the loop. Get the timing right, and the rest is tuning.


Originally published at getmichaelai.com

Top comments (0)