DEV Community

Vhub Systems
Vhub Systems

Posted on

How to Build a Prospect Research Bot That Automatically Pulls Company News Before Every Sales Call

How to Build a Prospect Research Bot That Automatically Pulls Company News Before Every Sales Call

You're three minutes away from a discovery call. You open the prospect's company website. The "About" page is the same as it was six months ago. You check LinkedIn — nothing new jumps out. You Google their name and get a press release from 2023.

You join the call blind.

This is the default experience for most AEs and SDRs. Pre-call research is the highest-leverage activity in sales prep — and also the most automatable. Here's how to build a bot that pulls a 5-point company brief into Slack 30 minutes before every calendar call, for under $10/month.


The Problem: Flying Blind Into Discovery

Manual pre-call research takes 15–30 minutes per prospect. At five calls per day, that's 1.5–2.5 hours of prep — every single day — that involves opening tabs, scrolling LinkedIn, checking Google News, and trying to remember if you saw a funding announcement last month.

The intel that actually moves a conversation forward is:

  • Recent news — layoffs, funding rounds, product launches, executive changes
  • Hiring signals — is the company growing, contracting, or pivoting?
  • Open roles — what problems are they hiring to solve?
  • Tech signals — what tools appear in job descriptions?
  • Talking points — what to lead with to show you've done your homework

Doing this manually is slow. Skipping it is worse — showing up to a call without context kills rapport and signals to the buyer that you don't care.


What Enterprise Tools Charge for This

The enterprise market has decided this problem is worth a lot of money:

  • Chorus.ai — $1,200+/user/year for call intelligence with some pre-call context
  • Clari — $60–$90/user/month for pipeline analytics and buyer signals
  • Bombora — $2,000–$5,000/month for intent data on target accounts

These are built for large revenue teams with operations budgets. If you're a founder doing sales, a scrappy SDR team, or a sales ops lead trying to automate without enterprise spend, none of these are accessible.

The actual data you need is publicly available. The only cost is the compute to pull it automatically.


The Architecture: A 3-Source Brief

The pre-call brief pulls from three sources:

  1. Google News queries"[Company Name]" funding OR acquisition OR layoff OR launch via SERP scraping
  2. LinkedIn job listings — current open roles at the company as a hiring signal
  3. Template engine — format the raw data into a 5-point Slack message

Let's build each piece.


Step 1: Pull Company News with google-serp-scraper

Apify's lanky_quantifier/google-serp-scraper runs Google queries and returns structured results — titles, URLs, snippets, published dates. No browser required, no proxy management.

const { ApifyClient } = require('apify-client');

const client = new ApifyClient({ token: process.env.APIFY_API_TOKEN });

async function getCompanyNews(companyName) {
  const query = `"${companyName}" (funding OR acquisition OR layoff OR "product launch" OR "new CEO" OR partnership)`;

  const run = await client.actor('lanky_quantifier/google-serp-scraper').call({
    queries: query,
    maxResults: 5,
    dateRange: 'past_3_months'
  });

  const { items } = await client.dataset(run.defaultDatasetId).listItems();

  return items.slice(0, 5).map(item => ({
    title: item.title,
    snippet: item.description,
    url: item.url,
    date: item.date || 'recent'
  }));
}
Enter fullscreen mode Exit fullscreen mode

This returns up to five recent news results per company. The past_3_months filter keeps the brief relevant — you don't need a press release from 18 months ago on a discovery call.


Step 2: Pull Hiring Signals with linkedin-job-scraper

Hiring volume is one of the most reliable leading indicators in sales. A company posting 10 backend engineering roles is expanding infrastructure. A company posting zero roles after previously active hiring may be in cost-cutting mode.

async function getHiringSignals(companyName) {
  const run = await client.actor('lanky_quantifier/linkedin-job-scraper').call({
    queries: [`${companyName} jobs`],
    maxResults: 10
  });

  const { items } = await client.dataset(run.defaultDatasetId).listItems();

  // Extract open roles and tech signals from job titles/descriptions
  const roles = items.map(job => job.title).filter(Boolean);

  const techKeywords = ['Salesforce', 'HubSpot', 'Snowflake', 'dbt', 'Kubernetes',
    'Terraform', 'Python', 'React', 'AWS', 'Azure', 'GCP'];

  const techSignals = new Set();
  items.forEach(job => {
    const text = `${job.title} ${job.description || ''}`;
    techKeywords.forEach(kw => {
      if (text.includes(kw)) techSignals.add(kw);
    });
  });

  return {
    openRoles: roles.slice(0, 5),
    roleCount: items.length,
    techStack: [...techSignals].slice(0, 4)
  };
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Generate the Brief

Combine both data sources into a readable 5-point summary:

function generateBrief(companyName, news, hiring) {
  const lines = [
    `*Pre-Call Brief: ${companyName}*`,
    ``,
    `*📰 Recent News (last 90 days):*`,
    ...(news.length > 0
      ? news.map(n => `• ${n.title}${n.date}`)
      : ['• No major news found']),
    ``,
    `*👥 Headcount Signal:*`,
    `• ${hiring.roleCount} open role${hiring.roleCount !== 1 ? 's' : ''} currently posted`,
    ``,
    `*🔧 Tech Stack Signals:*`,
    hiring.techStack.length > 0
      ? `• Seen in job descriptions: ${hiring.techStack.join(', ')}`
      : `• No tech signals detected`,
    ``,
    `*📋 Open Roles (sample):*`,
    ...(hiring.openRoles.length > 0
      ? hiring.openRoles.map(r => `• ${r}`)
      : ['• No active postings found']),
    ``,
    `*💬 Suggested Talking Points:*`,
    news.length > 0 ? `• Reference the recent news in your opener` : null,
    hiring.roleCount > 5 ? `• "It looks like you're actively scaling — what does that mean for your [relevant department]?"` : null,
    hiring.techStack.length > 0 ? `• Ask about their experience with ${hiring.techStack[0]} if relevant to your product` : null,
  ].filter(Boolean);

  return lines.join('\n');
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Wire It to Google Calendar + Slack

Check upcoming calendar events and send the brief 30 minutes before each call:

const axios = require('axios');

async function sendToSlack(message) {
  await axios.post(process.env.SLACK_WEBHOOK_URL, { text: message });
}

async function runPreCallBot(upcomingEvents) {
  const now = Date.now();
  const thirtyMin = 30 * 60 * 1000;

  for (const event of upcomingEvents) {
    const eventStart = new Date(event.start.dateTime).getTime();
    const minutesUntilCall = (eventStart - now) / 60000;

    // Brief the rep 25–35 minutes before call start
    if (minutesUntilCall > 25 && minutesUntilCall <= 35) {
      const companyName = extractCompanyFromEvent(event); // parse from title or attendee domain
      if (!companyName) continue;

      const [news, hiring] = await Promise.all([
        getCompanyNews(companyName),
        getHiringSignals(companyName)
      ]);

      const brief = generateBrief(companyName, news, hiring);
      await sendToSlack(brief);

      console.log(`Brief sent for: ${companyName}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Run this script on a cron every 10 minutes. Connect it to your Google Calendar via the Calendar API (or via a Zapier/Make webhook if you prefer no-code) and it will self-trigger as calls approach.


Cost: Under $10/Month

Component Cost
google-serp-scraper (5 queries/call × 5 calls/day) ~$0.015/call, ~$2.25/month
linkedin-job-scraper (1 run/company) ~$0.05/run, ~$7.50/month at 5 calls/day
Slack webhooks Free
Google Calendar API Free
Total ~$8–$10/month

Compare that to Chorus.ai at $1,200+/user/year or Clari at $720–$1,080/user/year. For a 5-person sales team, enterprise tools cost $3,600–$6,000/year for something you can self-host for under $120/year.


What to Add Next

Once the base brief works, extend it:

  • Funding alerts: parse Crunchbase RSS or run a SERP query for "[company]" site:techcrunch.com OR site:businesswire.com to catch funding rounds
  • Executive changes: add query term "new CEO" OR "appointed" OR "joins as" to the news search
  • CRM sync: after the call, push the brief as a HubSpot note via their API — instant call context in your CRM history
  • Summaries via LLM: pipe the raw news snippets through an LLM to produce a two-sentence "why this matters to your pitch" narrative

The core insight: the data you need for a great discovery call is public. The only question is whether you spend 20 minutes finding it manually or $0.20 and 30 seconds automating it.


Built with lanky_quantifier/google-serp-scraper (98.3% success rate, 172 runs/30d) and lanky_quantifier/linkedin-job-scraper on Apify.

Top comments (0)