Aller au contenu

AI Detection of Business Signals: Building a Useful RevOps System

There comes a point where commercial databases are no longer enough.

They can tell you a company exists. They sometimes give you an industry, a size, a website, a LinkedIn account, a few contacts.

But they rarely answer the most interesting question:

Why does this company deserve to be contacted right now?

That question is what gradually led me to work on a broader topic: business signal detection using AI, scraping, automated workflows and some RevOps logic. Not to build a magic machine to sell. Not to replace salespeople. But to better prepare sales work, understand the movements of a company, and turn fairly noisy public data into actionable context.

This page is an entry point. It connects several technical experiments around scraping, competitive monitoring, expansion signals and semi-automated prospecting, and explains the overall reasoning behind these projects.

Summary

  • What this system does: automatically detect expansion, competitive and technical signals from WTTJ, LinkedIn, Trustpilot and the web.
  • Main stack: n8n · Scrapy · Supabase · OpenRouter · Redis · Apify.
  • The real challenge: not collection, but filtering noise, avoiding false positives, and making the output actionable.
  • The role of AI here: classify and summarize already-structured signals, never decide on its own.
  • What I mostly learned: a useful RevOps system is not the one that automates the most, it is the one that makes the best context available at the right moment.

  • Detecting Web Technologies with Scrapy

    How I built a tech stack detection engine from HTML, scripts, cookies, headers and signatures.

    Read the note

  • The SDR Lead Machine

    How I assembled a company database, Hunter.io, pain points, customer references, n8n, Microsoft Lists and Power BI to help SDRs better prepare their prospecting.

    Read the note

  • Multi-Source Competitive Monitoring

    How I combined Trustpilot, LinkedIn, websites, Supabase and an LLM to extract useful competitive signals.

    Read the note

  • Expansion Signals with WTTJ, LinkedIn and n8n

    How I used WTTJ via Algolia, LinkedIn, news pages and Redis to detect growth indicators at B2B companies.

    Read the note


The Real Problem: Salespeople Rarely Lack Data

The problem is not having data. In B2B, you can already buy or enrich a lot of information: name, domain, industry, size, country, LinkedIn page, contacts, emails, job titles, supposed technologies, funding rounds, public news.

The real problem lies elsewhere.

Raw data rarely tells you what to do with it.

A 300-person SaaS company might be interesting. But why now? What has changed? Are they hiring? Are they opening a new market? Are they changing their stack? Are they getting negative reviews on their support? Are they looking for profiles that indicate an internal transformation?

That is where the concept of business signals becomes interesting.

The key insight

A commercial database describes a company. A business signal describes a movement.

And in many sales contexts, the movement matters more than the static record.


What I Call a Business Signal

A business signal is not just a news item. It is public or semi-structured information that can indicate a company is going through a particular moment.

Detected signal What it might suggest Possible commercial angle
Heavy recruiting on WTTJ Growth, expansion, team structuring Offer a solution that supports scaling
New LinkedIn posts about a market Repositioning or commercial expansion Adapt messaging to this new market
Recurring negative Trustpilot reviews Customer friction, support issue, product problem Identify a credible competitive angle
Marketing stack change Migration, digital maturity, ongoing project Propose an audit, integration or alternative
New product page published New offer, repositioning Monitor the evolution of commercial messaging
Surge in recruitment content Internal growth or difficulty attracting talent Spot HR or operational priorities

The signal is not necessarily proof. It is often a clue. And that is precisely why you need to be careful.

A signal is not a truth

A job posting does not prove a company is in hypergrowth. A negative review does not prove a competitor is struggling. A script detected in HTML does not always prove a technology is actually in use.

The system should help formulate a hypothesis, not produce an artificial certainty.


Why This Topic Interested Me

At first, I did not think I was working on a "RevOps system."

I was starting from much more concrete problems. In my prospecting workflows, I was spending too much time opening websites, inspecting source code, looking at loaded scripts, searching for marketing tools, checking whether a company was still publishing, reading barely usable LinkedIn posts, looking at job listings, cross-referencing information across several tabs, and trying to turn all of that into a credible sales message.

Each task was simple. But the whole thing was slow, repetitive and hard to industrialize properly.

The topic interested me because it sits exactly at the intersection of several domains I like: the web, scraping, automation, AI, data, prospecting, operational workflows and product logic.

It is not just a technical topic. It is also a system design topic.

How do you collect information without drowning in it? How do you keep reasoning understandable? How do you stop AI from deciding everything for you? How do you build something useful for someone who actually needs to sell afterward?


What I Wanted to Build

I wanted to build an actionable commercial intelligence layer. Not a CRM. Not an autonomous "AI SDR" platform. Not a tool that automatically sends 10,000 messages.

More like a system that helps answer a few simple questions:

  • which companies deserve attention this week?
  • why now?
  • what context has been detected?
  • what source allows verification?
  • what commercial angle might be relevant?
  • what message could be prepared, but not sent without validation?
Public data
Automated collection
Signal extraction
AI qualification
Prioritization
Assisted sales action

What interested me most was the transition between available information and actionable information.


Starting Constraints

I did not want to start from an overly theoretical architecture.

Constraint Consequence
Limited budget Avoid expensive APIs or closed platforms
Need to iterate fast Use n8n, Python, Supabase, OpenRouter
Heterogeneous sources Plan for cleaning, fallbacks, errors
Results usable by humans Keep sources, evidence and reasoning
No complete black box Avoid AI scoring that cannot be explained
Unstable web data Accept timeouts, false positives, broken pages

The temptation was to make everything "intelligent." But the further I went, the more I realized that robustness came mostly from simple components: well-identified sources, readable rules, scoped prompts, strict JSON output, basic deduplication, explainable scoring.

What I learned fairly quickly

A useful RevOps system is not necessarily the one that automates the most. It is often the one that makes the best context available at the right moment.


Why Existing Solutions Did Not Work for Me

There are already many tools around sales intelligence, monitoring, enrichment and intent data. The problem, in my case, was not their existence. It was their lack of flexibility for experimentation.

Tool type What bothered me
B2B databases Useful data, but often static
Intent data tools Opaque scoring, hard to audit
Monitoring tools Too generic, lots of noise
Tech detection extensions Poorly suited to automated workflows
Sales intelligence platforms High cost, closed logic
Off-the-shelf scrapers Hard to customize, strong dependency

I wanted to be able to quickly modify sources, detection rules, thresholds, prompts, output formats and triggered actions. And above all, I wanted to see the reasoning.

Commercial information is not useful simply because it exists. It becomes useful when you understand where it comes from, why it was retained, what it suggests, and what it does not allow you to claim.


Overall Architecture

Across projects, the general architecture started to look like this:

flowchart TD
    A[Public sources] --> B[Automated collection]

    A1[Websites] --> B
    A2[LinkedIn] --> B
    A3[WTTJ] --> B
    A4[Trustpilot] --> B
    A5[Company databases] --> B

    B --> C[Cleaning & normalization]
    C --> D[Signal extraction]

    D --> D1[Technical signals]
    D --> D2[Expansion signals]
    D --> D3[Competitive signals]
    D --> D4[Prospecting signals]

    D1 --> E[AI qualification]
    D2 --> E
    D3 --> E
    D4 --> E

    E --> F[Explainable scoring]
    F --> G[Supabase storage]
    G --> H[Operational interface]

    H --> I[SDR action]
    H --> J[RevOps monitoring]
    H --> K[Reporting]

The important idea: AI is not placed at the beginning. I do not use it to "guess" from nothing. I use it after a collection and structuring step.

flowchart LR
    A[Raw data] --> B[Parsing]
    B --> C[Structured context]
    C --> D[AI analysis]
    D --> E[Actionable JSON]
    E --> F[Human action]

Design principle

The more structured the input sent to the LLM, the more stable the output. The prompt should not compensate for a dirty data pipeline.


The Main Signal Families

I gradually distinguished several signal families.

mindmap
  root((Business signals))
    Technical
      Marketing stack
      CMS
      CRM
      Tracking
      Visible technical debt
    Expansion
      Recruiting
      New markets
      New offers
      Team growth
    Competitive
      Customer reviews
      Positioning
      Pricing
      Product changes
    Commercial
      Likely pain points
      Relevant references
      Message angles
      SDR priority

This categorization helped me avoid mixing everything together. A technical signal does not carry the same level of evidence as an expansion signal. A Trustpilot review does not have the same nature as a WTTJ job posting. Each source has its use, but also its blind spots.


Stack Used

The stack evolved through experimentation, but several components kept coming back.

Tool Role Why this choice
Scrapy Web crawling and HTML collection Fast, structured, suited to volume
Playwright JavaScript fallback Useful when the initial HTML is empty
n8n Workflow orchestration Fast to prototype and connect components
Supabase Structured storage Simple, PostgreSQL, convenient for history
OpenRouter LLM calls Flexible, lets you test multiple models
GPT-4o-mini AI analysis at reasonable cost Sufficient for classification and extraction
Apify LinkedIn collection Avoids maintaining a fragile scraper
Hunter.io Company and contact enrichment Useful for going from company to contact
Redis Concurrency control Avoids saturating external APIs
Microsoft Lists Simple SDR interface Understandable by an operational team
Power BI Reporting Lets you track volume, statuses and performance

Why n8n

n8n served as my backbone. Not because it is perfect, but because it is very effective for quickly testing chains of actions. What I appreciated: visualizing the workflow, quickly connecting APIs, testing a prompt, inspecting inputs and outputs, relaunching an execution, prototyping before writing clean code.

What I liked less: workflows quickly get large, readability drops when there are too many branches, and some complex transformations would be cleaner in code.

The n8n trap

n8n gives the impression you can assemble everything very quickly. That is true at the start. But as soon as the business logic grows, you need to be disciplined: naming, sub-workflows, logs, normalized outputs, error handling.

Why Scrapy

Scrapy entered the system through the web technology detection project. At first, I simply wanted to avoid opening sites one by one to understand their stack.

The key point: Scrapy does not detect anything on its own. It collects signals. The business logic lives elsewhere: in the signatures, the scoring and the interpretation.

flowchart TD
    A[Domain list] --> B[Scrapy spider]
    B --> C[HTML]
    B --> D[Scripts]
    B --> E[Headers]
    B --> F[Cookies]
    B --> G[Meta tags]

    C --> H[Signature engine]
    D --> H
    E --> H
    F --> H
    G --> H

    H --> I[Confidence score]
    I --> J[Detected technologies]
    J --> K[RevOps workflow]

To go further on this part: Building a Web Technology Detector with Scrapy

Why Supabase

Supabase mostly helped me keep a clean foundation: companies, domains, signals, crawl results, WTTJ slugs, enrichments, statuses, history.

The temptation at first is to route everything through JSON or CSV files. That is fine for testing. But as soon as you want to compare over time, deduplicate, score and track history, a database becomes necessary.

Simplified structure:

create table companies (
  id uuid primary key default gen_random_uuid(),
  name text,
  domain text,
  linkedin_url text,
  industry text,
  headcount text,
  country text,
  wttj_slug text,
  created_at timestamptz default now()
);

create table business_signals (
  id uuid primary key default gen_random_uuid(),
  company_id uuid references companies(id),
  source text,
  signal_type text,
  title text,
  summary text,
  evidence_url text,
  confidence_score numeric,
  detected_at timestamptz default now(),
  raw_payload jsonb,
  prompt_version text
);

Why AI, But Not Everywhere

AI is useful in this system, but only in certain places.

I used it to summarize signals, classify information, identify a commercial angle, distinguish noise from signal, formulate a hypothesis, generate JSON output, and prepare a sales brief.

I avoided using it to decide truth on its own, to scrape, to deduplicate without a stable key, to replace simple rules, to hide sources, or to invent missing context.

Personal rule

If a simple rule is enough, I prefer a simple rule. AI comes in when the context becomes ambiguous, narrative or hard to reduce to a condition.


Step-by-Step Construction

Step 1 — Build a Company Database

Everything starts with a list. In the SDR lead machine project, I started with a company website database pulled from several sources. The goal was not to have a perfect database from the start, it was actually the opposite: accept an imperfect database, then use the following steps to filter it.

flowchart LR
    A[Domain sources] --> B[Cleaning]
    B --> C[Deduplication]
    C --> D[Company database]
    D --> E[Crawl]
    E --> F[Qualification]

You often want to start with "perfect data." In practice, it does not exist. You start with noise, then build mechanisms to filter, enrich, score, exclude and learn.

Step 2 — Detect Technical Signals

The first industrialized signal family concerns web technologies.

{
  "domain": "example-store.com",
  "technologies": [
    {
      "name": "Shopify",
      "confidence": 0.97,
      "signals": ["cdn.shopify.com", "_shopify_y", "shopify-checkout"]
    },
    {
      "name": "Klaviyo",
      "confidence": 0.91,
      "signals": ["static.klaviyo.com", "__kla_id"]
    }
  ],
  "meta": {
    "crawl_time_ms": 1840,
    "javascript_rendered": false,
    "redirects": 1
  }
}

This type of output can be reused to identify companies using a competing technology, detect e-commerce stacks, estimate marketing maturity, feed a scoring model or personalize a message. But it requires discipline: each detection must keep its evidence.

Step 3 — Enrich Companies and Contacts

Once companies are filtered, the next step is enrichment. In the SDR workflow, Hunter.io was used to retrieve company information, contacts, job titles and sometimes emails.

But enrichment alone is not enough. A contact without context often produces a generic message. Context without a contact remains hard to act on. You need both.

Field note

The hardest part is not finding contacts. The hardest part is not generating a list of useless contacts.

Step 4 — Cross-Reference with Pain Points and References

Personalization should not come only from the LLM. In my approach, I preferred preparing business databases: pain points by competing technology, customer references by industry, differentiating arguments, integration capabilities.

The LLM therefore does not start from a blank page. It receives scoped context:

{
  "company": {
    "name": "Example Company",
    "industry": "Retail",
    "detected_technologies": ["Klaviyo", "Shopify"]
  },
  "pain_points": [
    "difficulty synchronizing CRM data",
    "limited segmentation on some advanced scenarios"
  ],
  "relevant_references": [
    {
      "name": "Client A",
      "sector": "Retail",
      "use_case": "CRM automation + email"
    }
  ],
  "commercial_goal": "prepare a contextualized prospecting angle"
}

Instead of asking "Write a personalized email for this company," you ask: "Based on the detected signals, known pain points and relevant references, suggest a careful, verifiable and useful commercial angle for an SDR." The difference in output quality is significant.

Step 5 — Detect Expansion Signals

Expansion signals come from complementary sources.

Source What it can reveal Main limitation
WTTJ Active recruiting, job types sought, location Requires good company / slug mapping
LinkedIn Public announcements, launches, partnerships A lot of noise
News pages Official messaging, new markets, new offers Heterogeneous web structures
flowchart TD
    A[(Supabase companies)] --> B[n8n Scheduler]
    B --> C{Loop companies}

    C --> D[WTTJ via Algolia]
    C --> E[LinkedIn via Apify]
    C --> F[News pages]

    D --> G[Job parsing]
    E --> H[Post parsing]
    F --> I[Content parsing]

    G --> J[Structured context]
    H --> J
    I --> J

    J --> K[AI analysis]
    K --> L[Signal JSON]
    L --> M[(Supabase)]

An important lesson about WTTJ: going through the Algolia requests visible on the frontend is much more stable than parsing HTML. It is not a hack, it is the normal behavior of a client-side search-only key. But it creates another difficulty: you need to know the correct WTTJ slug for the company.

Classic mistake

When the slug is missing, the API can return zero results without an error. Technically, everything works. Functionally, the signal is lost.

For the details: Detecting Company Expansion Signals with WTTJ, LinkedIn and n8n

Step 6 — Build Multi-Source Competitive Monitoring

Competitive monitoring adds another difficulty: the signal is rarely isolated. A single Trustpilot review can be anecdotal. A single LinkedIn post can be marketing. When multiple sources tell a coherent story, the signal becomes more interesting.

flowchart TD
    A[Competitor] --> B[Trustpilot]
    A --> C[LinkedIn]
    A --> D[Website / blog]

    B --> E[Customer friction]
    C --> F[Visible movements]
    D --> G[Official messaging]

    E --> H[Context assembly]
    F --> H
    G --> H

    H --> I[AI analysis]
    I --> J[Competitive signal]
    J --> K[Prioritization]
Example of expected output
{
  "competitor": "Example Competitor",
  "signal_type": "customer_support_weakness",
  "confidence": 0.78,
  "sources": ["trustpilot", "linkedin"],
  "summary": "Several recent reviews mention long response times. Meanwhile, the company is communicating about strong customer growth.",
  "commercial_angle": "Position support quality and responsiveness as differentiators, without directly attacking the competitor.",
  "evidence": [
    { "source": "trustpilot", "url": "https://example.com/review/123" },
    { "source": "linkedin", "url": "https://linkedin.com/posts/example" }
  ]
}

For the details: Building Multi-Source Competitive Monitoring with Trustpilot, LinkedIn and the Web

Step 7 — Make the System Actionable for SDRs

A signal sitting in a database is not very useful. You need an operational output.

In the SDR project, the interface went through Microsoft Lists, with simple statuses:

Prospect status Email status Sales status
new not sent to process
in progress sent follow-up
closed replied meeting
off-target error declined

It is not the most glamorous interface. But it is understandable by a team already working in a Microsoft environment.

flowchart LR
    A[Qualified signals] --> B[Prioritization]
    B --> C[SDR assignment]
    C --> D[Microsoft Lists]
    D --> E[Teams notification]
    D --> F[Status tracking]
    F --> G[Power BI]

What worked

Adoption depends less on the sophistication of the system than on the clarity of the output. If the salesperson understands why a company appears in their list, the system becomes useful.


Scoring Model

I was not trying to create a perfect score. I was trying to create a readable one.

def compute_signal_score(signal):
    score = 0

    if signal["source"] == "wttj":
        score += 20
    if signal["source"] == "linkedin":
        score += 10
    if signal["source"] == "trustpilot":
        score += 15

    if signal.get("recency_days", 999) <= 30:
        score += 20
    if signal.get("has_multiple_sources"):
        score += 25
    if signal.get("matches_icp"):
        score += 20

    return min(score, 100)

This scoring is deliberately simple. It does not claim to produce a statistical truth. It is used to sort, filter, prioritize. In an operational system, that is often enough to get started.

To improve later

Scoring becomes smarter with history: which signals actually lead to a reply? which signals produce meetings? which signals are mostly noise?


Indicative Signal Distribution

After several weeks of execution, here is how signals and their estimated relevance break down:

pie title Distribution of detected signals by source
    "LinkedIn" : 35
    "WTTJ" : 25
    "Websites / news" : 20
    "Trustpilot" : 12
    "Tech detection" : 8

The signal-to-noise ratio varies considerably by source:

Source Estimated relevance Comment
Tech detection ~70% Precise signal if signatures are good
WTTJ ~65% Reliable, but depends on slug and deduplication
Trustpilot ~55% Biased toward extreme experiences
Websites / news ~45% Heterogeneous, blogs often abandoned
LinkedIn ~25% Lots of generic employer brand content

Errors and Problems Encountered

1. Assuming Web Data Is Clean

It is not. Sites redirect poorly. Certificates expire. Pages change. Content is rendered in JavaScript. Blogs have no dates. Slugs do not match company names. APIs respond differently depending on the case.

In a signal detection workflow, edge cases are the norm.

The real cost

The main cost is not writing the first crawler. The main cost is managing exceptions.

2. Triggering AI Too Early

At first, you can be tempted to send a lot of raw content to the LLM. Problems encountered: responses too long, hallucinations, poor prioritization, hard to parse, higher cost, results hard to compare.

What works better:

flowchart LR
    A[Raw content] --> B[Cleaning]
    B --> C[Useful field extraction]
    C --> D[Structured context]
    D --> E[Scoped prompt]
    E --> F[Strict JSON]

3. Underestimating Deduplication

A signal can appear multiple times: same LinkedIn post retrieved twice, WTTJ job reposted, news page crawled on multiple dates, customer review already analyzed.

The simple solution: generate a hash.

import hashlib

def make_signal_hash(company_id, source, title, published_at):
    raw = f"{company_id}:{source}:{title}:{published_at}".lower().strip()
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()

4. Confusing Volume with Value

More signals does not mean a better system. A workflow that surfaces 200 weak signals per week quickly becomes unusable.

Bad indicator Better indicator
Number of signals detected Number of actionable signals
Number of sources crawled Quality of useful sources
Number of emails generated Rate of messages actually validated
Number of companies enriched Number of relevant companies
Average score Conversion by signal type

Simple formulation

The goal is not to find more information. The goal is to reduce the time needed to understand what to do.


What Worked

Cross-Referencing Sources

Each source alone is imperfect. But cross-referencing changes a lot.

Source 1 Source 2 Stronger interpretation
WTTJ: Sales recruiting LinkedIn: new market announcement Likely commercial expansion
Trustpilot: support complaints Website: premium support messaging Competitive angle to verify
Competing tech detection Relevant customer reference More contextualized SDR message
Active company blog Product recruiting Transformation or launch underway

Strict JSON Outputs

Another point that worked well: forcing structured outputs.

{
  "is_relevant": true,
  "signal_type": "expansion",
  "confidence": 0.82,
  "summary": "The company is recruiting several sales profiles in Europe, suggesting an expansion phase.",
  "evidence": {
    "source": "wttj",
    "url": "https://example.com/jobs"
  },
  "recommended_action": "prepare a growth-support oriented approach"
}

Strict JSON makes the system more testable, more storable, more exploitable and easier to compare over time.

Keeping Humans in the Loop

The goal is not for the system to decide on its own. The goal is for it to better prepare human work. The SDR must be able to see the source, understand the reasoning, invalidate a signal, change a status, adapt the message, decide not to contact.

flowchart TD
    A[System detects] --> B[Human verifies]
    B --> C[Human adjusts]
    C --> D[Sales action]
    D --> E[Result]
    E --> F[Future learning]

The right balance

Automate the preparation. Keep the decision human.


What I Learned

  • Clean logs from the start. Handled errors, timeouts, retries, typed outputs, preserved sources, deduplication, versioned prompts, readable scoring, historical storage. The boring details make the quality of the system.
  • Inspect the network before scraping. WTTJ would have taken several days with HTML parsing. Algolia reduced it to under an hour. Opening DevTools first became a reflex.
  • Log "0 results" differently from errors. An empty return can be correct or symptomatic. Treating them the same hides bugs.
  • A signal only has value if it helps make a decision. You therefore need to think about the display as much as the collection. A good signal should answer four questions: what was detected? why might it matter? what evidence can be checked? what can be done next?
  • Raw totals are a trap. Variation over time is more useful than instantaneous volume. What you really want is a rolling 4-week history.
  • The persona in the prompt changes output quality. "Analyze" produces summaries. "You are looking for concrete upsell opportunities" produces actions.
  • RevOps is not just about tooling. It is a way of connecting data, workflows, sales teams, existing tools, reporting and field learnings.
  • The value comes from the complete loop. Without field feedback, the system remains a hypothesis-generating machine. With field feedback, it can progressively improve.
flowchart LR
    A[Collection] --> B[Qualification]
    B --> C[Action]
    C --> D[Result]
    D --> E[Analysis]
    E --> A

Current Limitations

Scraping Remains Fragile

Even with Scrapy, Playwright, Apify or indirect APIs, collection remains dependent on external sources: HTML structure changes, anti-bot protections, costly JavaScript rendering, deleted pages, undated content, undocumented APIs, variable costs depending on volume.

You need to accept this fragility from the start.

Signals Are Not All Comparable

A WTTJ job posting, a Trustpilot review, a Klaviyo script and a LinkedIn post do not have the same reliability, freshness, bias, commercial value, or level of evidence. Scoring must therefore remain cautious.

The System Does Not See Everything

It sees what is public. It does not see internal projects, commercial discussions, unpublished organizational changes, backend tools, budget decisions, or actual buying cycles.

Do not forget

A signal system does not read companies' minds. It observes public traces and proposes hypotheses.

Scaling Requires Another Level of Rigor

A prototype that works on 100 companies does not necessarily work on 10,000. At larger scale, you need to seriously address execution concurrency, API quotas, costs, pagination, silent errors, failure recovery and data governance.


What I Would Do Differently

I Would Version Prompts from the Start

At first, prompts evolve quickly. You change a sentence, add a field, change an instruction, then you no longer know which version produced which result.

/prompts
  /signals
    expansion_v1.md
    expansion_v2.md
    competitor_watch_v1.md
  /sales
    email_generation_v1.md
    account_brief_v1.md

With in the database: alter table business_signals add column prompt_version text;

I Would Build a Business Test Suite

Not just technical tests. A real set of cases:

Case Expected result
5 recent WTTJ job postings across multiple countries Expansion signal
Generic employer brand LinkedIn post Not relevant
10 recent negative reviews about support Competitive signal
Blog abandoned for 2 years Ignore
Tech detection with a single ambiguous HTML word Low confidence

This is probably what is most missing from many AI workflows: business tests.

I Would Separate Orchestration and Business Logic Earlier

n8n is very convenient, but all the logic should not live in the nodes.

flowchart TD
    A[n8n orchestration] --> B[Business services]
    B --> C[Scraping]
    B --> D[Scoring]
    B --> E[Deduplication]
    B --> F[LLM analysis]
    B --> G[Storage]

    G --> H[Interface]
    H --> I[User feedback]
    I --> G

System Evolution

flowchart LR
    P[Prototype\nLocal Scrapy] --> W[First workflow\nn8n + enrichment]
    W --> Q[AI qualification\nStrict JSON]
    Q --> S[Storage\nSupabase + history]
    S --> I[SDR interface\nLists + Teams]
    I --> R[Reporting\nPower BI]
    R --> N[Next step\nfeedback loop + adaptive scoring]

FAQ

What is a B2B business signal?

A business signal is public or semi-structured information indicating that a company is going through a particular moment: heavy recruiting, stack change, recurring negative customer reviews, geographic expansion announcement.

Unlike a static company record, a signal describes a movement, not a state. It is that movement that makes sales outreach better timed.

What sources should you use to detect business signals?

In my practice, web technology detection (Scrapy) and WTTJ job postings via Algolia have the best signal-to-noise ratio. LinkedIn generates a lot of noise but remains useful for expansion announcements combined with other sources. Trustpilot is interesting for competitive signals.

The key: a signal confirmed by multiple sources is far more reliable than an isolated signal.

Do you really need AI to detect business signals?

No, not necessarily. Simple rules are sufficient for many signals: more than 15 recent WTTJ job postings across two different countries is a readable expansion signal without an LLM.

AI becomes useful when context becomes ambiguous or narrative: summarizing LinkedIn posts, qualifying whether a stack change is relevant to your offer, or identifying an angle within a set of heterogeneous signals.

How do you avoid false positives in a RevOps system?

Three mechanisms helped me the most:

  1. Hash-based deduplication -- prevents a reposted job from generating a new signal.
  2. Source cross-referencing -- require multiple concordant sources before scoring high.
  3. Strict JSON in prompts -- force structured output rather than free interpretation.

And above all: keep humans in the loop. The system prepares, the human validates.

Which AI model should you use to qualify business signals?

For classification, structured extraction and summarization tasks, gpt-4o-mini via OpenRouter offers a good cost-to-quality ratio. Output quality depends mostly on the prompt and the quality of the context sent, not just the model. Well-structured context with a scoped prompt produces more stable results than noisy context sent to a more powerful model.

How do you make the system usable by a sales team?

Adoption depends mostly on the clarity of the output. If the salesperson understands why a company appears in their list, with the source, context and an action suggestion, the system becomes useful. If the output is a list of unexplained scores, it will be ignored.

In my SDR project, Microsoft Lists with simple statuses and Teams notifications worked better than an over-engineered interface.


Conclusion: What This Project Really Shows

Looking back, I did not just build scraping or prospecting workflows.

I explored a fairly simple question:

How do you help a sales team better understand the right moment to act?

The answer is not purely technical. It involves data, scraping, AI, orchestration. But it mostly comes down to a discipline: not confusing information, signal and decision.

Information is something you collect. A signal is information that suggests a movement. A decision remains a human act, contextualized, sometimes cautious.

That is why I find the topic interesting. It forces you to build concrete, imperfect, but useful systems. Systems that do not replace sales work, but can make it less repetitive, more contextualized and more intelligent.

There is still a lot to improve: adaptive scoring, feedback loop, better historization, dedicated interface, business tests, source monitoring, real measurement of commercial impact.

But the direction seems right to me: start from public traces, structure them, cross-reference them, qualify them, make them actionable, then let humans decide. That is probably where AI is most interesting in a RevOps context, not as a magic layer on top of sales, but as a discreet engine for preparation, synthesis and context.


  • Scraping & tech detection

    Build a web technology detection engine with Scrapy.

    Read

  • Semi-automated prospecting

    Build an SDR lead machine with enrichment, scoring and operational tracking.

    Read

  • Competitive monitoring

    Combine Trustpilot, LinkedIn and the web to detect competitive movements.

    Read

  • Expansion signals

    Use WTTJ, LinkedIn, Algolia and n8n to detect growth indicators.

    Read