A ZoomInfo alternative, built for Almcoe.

Lean, industry-specific intent system for commercial HVAC, commercial refrigeration, cold storage, and rack refrigeration across Almcoe's full Texas footprint — DFW, Austin, and San Antonio. Built around two killer signals ZoomInfo can't match: parsed Schedule Service form submissions from contact@almcoe.com (pure declared intent), and Texas public permit filings (top-of-buying-cycle intent). No pixel dependency, no bidstream black box.

What this system does

Monitors a defined list of target accounts across multiple signal sources, scores buying intent, and alerts your team when an account crosses a threshold. No bidstream black box. Every signal is transparent and auditable.

Target Accounts
Across full Texas footprint
Intent Topics
Across 6 categories
Form Submissions Logged
0
From contact@almcoe.com
Est. Annual Cost
$500-3K
vs. ZoomInfo $40-50K

Why this vs. ZoomInfo Streaming Intent

FactorZoomInfo SIThis System
Strongest signalBidstream — inferred interestYour own form submissions — declared intent
Second signalPublisher network page viewsTexas permit filings — buying-cycle trigger
Account universe500K+ (most irrelevant)Your Texas TAM (~100 curated accounts)
Industry tuningGeneric B2B topic treeHVAC / refrigeration / cold storage only
Regional tuningGlobalDFW + Austin + SA permits, Texas chains
Cost$40K-50K/year$500-3K/year
Legal exposureBidstream sits in GDPR gray zonePublic record + your own inbox only

Next step

Open the Setup Guide. It walks through the nine tasks to stand this up, in order, with time estimates and vendor links.

Setup Guide

Seven steps. Half the work is done if you just complete steps 1-3.

Key insight for your situation: You don't control almcoe.com, but you get forwarded copies of every Schedule Service form submission to contact@almcoe.com. Those emails are the single highest-value intent signal available to you — higher than anything ZoomInfo can generate. Step 3 turns that inbox into structured data.
1Review topic taxonomy
20 min

Open Topic Taxonomy. Six categories pre-loaded: Commercial HVAC, Commercial Refrigeration, Cold Storage, Rack Refrigeration, Design & Installation, Compliance & Regulations. Keywords include brands you install — Hussmann, Hillphoenix, Trane, Carrier, Daikin.

  • Add brand names or jargon specific to Almcoe's service mix.
  • Remove any topics outside your actual scope.
2Review Texas-wide account list
1-2 hours

Open Target Accounts. Now covers full Texas footprint: DFW, Austin, San Antonio. Pre-loaded with HEB (SA HQ), Whataburger (SA HQ), Buc-ee's, Samsung Austin/Taylor, Tesla Giga Texas, Tito's, Toyota SA, Alcon Fort Worth, Dell Round Rock, plus the usual grocery/cold-storage/data-center/healthcare anchors.

  • Mark Tier 1 for active pursuit, Tier 2 for monitor, Tier 3 for awareness.
  • Add existing clients — you want signals on them too (expansion, champion moves).
  • Add any accounts you've lost bids on. Revenge pipeline is real.
3Turn contact@almcoe.com forwards into structured signals ★
30 min setup, ongoing use

This is your single highest-value signal. Open Form Intake.

  • When a forwarded submission hits your inbox, paste the email body into the intake tool.
  • The parser extracts company name, contact, location, equipment, problem type, emergency flag, warranty flag.
  • The system auto-matches to your account list — if it's a known target, it flags Tier 1/2/3 priority.
  • If the company is unknown, you can add them as a new account with one click.
  • Each submission scores as declared_intent (weight 60) — highest single-signal score in the system.

Level up later: Cloudflare Email Workers can automate this. Set up a forwarding rule from your mailbox → a dedicated address on almcoe.online → a Worker that parses and logs automatically. No pasting required. But for now, manual paste gets you 90% of the value.

4Wire up Texas permit filing feeds
3-5 hours across cities

Your second-highest signal. HVAC and refrigeration permits are public record. A filed mechanical permit means someone is literally about to build or retrofit — highest possible buying intent.

Filter by: valuation threshold ($100K+), permit type (commercial mechanical, refrigeration), and property type keywords (grocery, warehouse, restaurant, data center, industrial).

5LinkedIn job change & hiring signals
2 hours + billing

"Champion moves" — when a Facilities Manager you know leaves a client, you want to know their new employer immediately. Same for hiring spikes in MEP/plant-ops at target accounts.

  • Coresignal — LinkedIn-derived. Roughly $2-5K/mo at scale.
  • Proxycurl — pay-per-lookup, ~$0.01 per profile. Good for low volume.
  • Manual fallback: LinkedIn Sales Navigator ($99/mo) with saved lead searches + weekly notification digest. Not automated but effective for 1 person.
6News, funding, and expansion signals
2 hours

Expansion announcements and fundraises often precede permit filings by 3-9 months. Free sources, high signal.

  • Google News RSS — free. Per-account alerts on "expansion," "new facility," "groundbreaking," "distribution center." Easy to set up via https://news.google.com/rss/search?q=CompanyName+expansion.
  • SEC EDGAR — free. 8-K filings often announce new facilities before press does.
  • Crunchbase API — $49-499/mo tiers. Funding rounds, M&A, exec changes.
  • Texas Comptroller — new business filings, tax status changes.
7Configure scoring & alerts
30 min

Open Signal Scoring. Adjust weights to match your instincts. Defaults:

  • Declared intent (form submission) — 60 points
  • Permit filing on target account — 40 points
  • Known-contact job change — 35 points
  • Hot alert threshold — score ≥ 80
Minimum viable version: Steps 1-3 alone — topics + accounts + form intake — already beats what ZoomInfo gives you, because ZoomInfo doesn't see your incoming leads. Costs you nothing. Add permits (Step 4) and you have a real intent engine for under $500 in LLM costs.

Architecture

How data flows from source to signal to alert.

1. Data Sources
Almcoe Pixel
Dallas Permits
Fort Worth Permits
TDLR Licensing
Coresignal / LinkedIn
Crunchbase
Google News RSS
SEC EDGAR
2. Ingestion (Cloudflare Workers)
Collector Endpoint
Scheduled Scrapers
RSS Watchers
3. Enrichment
IP → Company (IPinfo)
Text → Topic (LLM classifier)
Account Match (fuzzy)
Firmographic enrich
4. Storage (D1 / Postgres)
Events Table
Accounts Table
Signals Table
Scores Table
5. Scoring Engine
Weighted Sum
Recency Decay
Tier Multiplier
Topic Match Boost
6. Activation
Slack Alerts
Email Digest
CRM Push
Dashboard

Tech stack recommendation

Frontend / DashboardSingle-page app (this one, extended) or Retool / Appsmith
Workers / ComputeCloudflare Workers (you already use CF for DNS)
StorageCloudflare D1 (SQLite) for small scale, Postgres (Supabase/Neon) for larger
QueueCloudflare Queues for deferred enrichment
Topic ClassifierClaude or GPT via API — classify page/news text against your topic tree
SchedulingCloudflare Cron Triggers
AlertsSlack incoming webhooks + Resend/SendGrid for email

Topic Taxonomy

Keywords and phrases that drive classification. Edit freely — these are your first-party intent categories.

Target Account Watchlist

Pre-loaded with Texas North accounts relevant to HVAC, commercial refrigeration, cold storage, and data center cooling. Edit freely.

Tier 1 (Active Pursuit)
0
Tier 2 (Monitor)
0
Tier 3 (Awareness)
0
Total
0
Company Category Tier Notes

Form Submission Intake ★ HIGHEST VALUE

Convert contact@almcoe.com email forwards into structured intent signals.

Why this matters more than anything else in the system: someone filling out the Schedule Service form has told you directly they want help. No inference, no IP lookup, no guessing. This is declared intent at its purest. ZoomInfo will never see this signal. You can.
Submissions logged
0
Tier 1 hits
0
Match to known targets
Emergency / after-hours
0
New accounts discovered
0
Companies not in your list

Paste a forwarded submission

When an email hits contact@almcoe.com and gets forwarded to you, copy the full email body (everything including field labels) and paste below. The parser looks for field names from the Schedule Service form and extracts structured data.

Logged submissions

Logged Company City Contact Type Match Score

Automation roadmap

Today: manual paste (works now, zero infrastructure)

Forward email → open this tool → paste → parse. Takes 20 seconds per submission.

Next level: Cloudflare Email Workers

Set up an email forwarding rule: contact@almcoe.com → intake@almcoe.online (your domain, Cloudflare-routed) → Email Worker parses and logs automatically. Removes the manual step. Roughly 2 hours to build.

Note: you can't add Email Routing to almcoe.com since you don't control DNS there. But you can set up a forward rule in Gmail/Outlook: "if from: contact@almcoe.com, forward to: intake@almcoe.online". Then Cloudflare Email Workers takes over from intake@almcoe.online.

Fully automated: IMAP watcher on a shared inbox

If corporate gives you access to contact@almcoe.com via IMAP, a Worker can poll the inbox every few minutes and process new submissions with zero human involvement. Requires IT coordination.

Web Pixel Optional / Later

Kept here for future reference. Not part of the current build.

Not applicable to your current setup. You don't control almcoe.com (Smart Care corporate does), and your own domains (almcoe.online, hub.almcoe.online) are internal-only. A pixel logging your employees' own IPs generates noise, not signal. Skip this entire section unless one of the following changes:
  • You launch a public-facing lead-gen site on a domain you control (e.g., almcoe.online with paid traffic)
  • Smart Care corporate gives you pixel-level access to a section of their site
  • You start hosting proposals on a public URL that prospects access
If any of those happen, the code below is ready to deploy.

Standard Pixel

<!-- Almcoe Intent Pixel v1.0 -->
<script>
(function() {
  var COLLECTOR_URL = 'https://intent-collector.almcoe.online/event';
  var SITE_ID = 'almcoe-main';

  function sendEvent(type, extra) {
    var payload = {
      site: SITE_ID,
      event: type,
      url: window.location.href,
      path: window.location.pathname,
      referrer: document.referrer,
      title: document.title,
      ts: new Date().toISOString(),
      session: getSession(),
      ua: navigator.userAgent,
      lang: navigator.language,
      extra: extra || {}
    };
    // Use sendBeacon when available for reliability
    var body = JSON.stringify(payload);
    if (navigator.sendBeacon) {
      navigator.sendBeacon(COLLECTOR_URL, body);
    } else {
      fetch(COLLECTOR_URL, { method: 'POST', body: body, keepalive: true });
    }
  }

  function getSession() {
    var key = 'almcoe_sid';
    var sid = sessionStorage.getItem(key);
    if (!sid) {
      sid = 'sid_' + Math.random().toString(36).slice(2) + Date.now().toString(36);
      sessionStorage.setItem(key, sid);
    }
    return sid;
  }

  // Fire pageview
  sendEvent('pageview');

  // Track deep engagement
  var engaged = false;
  setTimeout(function(){
    if (!engaged) { engaged = true; sendEvent('engaged_30s'); }
  }, 30000);

  // Track scroll depth
  var maxScroll = 0;
  window.addEventListener('scroll', function() {
    var pct = Math.round((window.scrollY + window.innerHeight) / document.body.scrollHeight * 100);
    if (pct > maxScroll + 25) {
      maxScroll = pct;
      sendEvent('scroll_depth', { depth: pct });
    }
  }, { passive: true });

  // Expose for manual events (e.g., proposal views)
  window.almcoeTrack = sendEvent;
})();
</script>

Worker Endpoint (Cloudflare)

Deploy this as a Worker at intent-collector.almcoe.online. It accepts the pixel payload, resolves IP to company via IPinfo, and stores events in D1.

// wrangler.toml:
// name = "intent-collector"
// main = "src/index.js"
// [[d1_databases]]
// binding = "DB"
// database_name = "almcoe_intent"

export default {
  async fetch(request, env) {
    // CORS
    if (request.method === 'OPTIONS') {
      return new Response(null, {
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'POST',
          'Access-Control-Allow-Headers': 'Content-Type'
        }
      });
    }
    if (request.method !== 'POST') return new Response('Method not allowed', { status: 405 });

    const body = await request.json();
    const ip = request.headers.get('CF-Connecting-IP');
    const country = request.cf?.country;

    // IP to company resolution (cached)
    const companyData = await resolveCompany(ip, env);

    await env.DB.prepare(
      `INSERT INTO events (site, event, url, path, referrer, title, ts, session, ua, ip, country, company_name, company_domain, extra)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
    ).bind(
      body.site, body.event, body.url, body.path, body.referrer, body.title,
      body.ts, body.session, body.ua, ip, country,
      companyData?.name || null, companyData?.domain || null,
      JSON.stringify(body.extra || {})
    ).run();

    return new Response(JSON.stringify({ ok: true }), {
      headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }
    });
  }
};

async function resolveCompany(ip, env) {
  // Check cache first
  const cached = await env.DB.prepare('SELECT company_name, company_domain FROM ip_cache WHERE ip = ? AND updated > ?')
    .bind(ip, Date.now() - 7*24*60*60*1000).first();
  if (cached) return { name: cached.company_name, domain: cached.company_domain };

  // Call IPinfo
  const resp = await fetch(`https://ipinfo.io/${ip}?token=${env.IPINFO_TOKEN}`);
  const data = await resp.json();
  const company = data.company || {};

  await env.DB.prepare('INSERT OR REPLACE INTO ip_cache (ip, company_name, company_domain, updated) VALUES (?, ?, ?, ?)')
    .bind(ip, company.name || null, company.domain || null, Date.now()).run();

  return { name: company.name, domain: company.domain };
}

D1 Schema

CREATE TABLE events (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  site TEXT, event TEXT, url TEXT, path TEXT, referrer TEXT,
  title TEXT, ts TEXT, session TEXT, ua TEXT,
  ip TEXT, country TEXT,
  company_name TEXT, company_domain TEXT,
  extra TEXT,
  created_at INTEGER DEFAULT (unixepoch())
);

CREATE INDEX idx_events_company ON events(company_domain);
CREATE INDEX idx_events_ts ON events(ts);
CREATE INDEX idx_events_session ON events(session);

CREATE TABLE ip_cache (
  ip TEXT PRIMARY KEY,
  company_name TEXT,
  company_domain TEXT,
  updated INTEGER
);

CREATE TABLE signals (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  account_domain TEXT,
  account_name TEXT,
  signal_type TEXT,  -- pixel, permit, hire, funding, news, etc.
  topic TEXT,
  score INTEGER,
  source TEXT,
  detail TEXT,
  ts TEXT,
  created_at INTEGER DEFAULT (unixepoch())
);

CREATE INDEX idx_signals_account ON signals(account_domain);
CREATE INDEX idx_signals_ts ON signals(ts);

Data Sources

Every API, feed, and data vendor — with real costs and what each one unlocks.

First-party (yours)

SourceWhat it unlocksCostPriority
contact@almcoe.com inboxSchedule Service form submissions = declared intentFree★ Critical
Email open/click (outbound)Engagement on your sent sequencesIncluded in ESPBuilt-in
CRM stage changesPipeline progression as a signalFreeHigh
Historical client listChampion tracking when they move employersFreeHigh

Third-party (paid)

SourceWhat it unlocksCostPriority
IPinfoIP → company resolution for pixel data$500-1500/moCritical
CoresignalLinkedIn job changes, hiring data$2-5K/moHigh
ProxycurlPer-profile LinkedIn lookupsPay-per-use, ~$0.01/lookupAlt to Coresignal
Crunchbase APIFunding rounds, M&A, exec changes$49-499/mo tiersHigh
ConstructConnectNational construction project feed w/ MEP breakout$3-10K/yrHigh
Dodge DataAlternative construction feed$5-15K/yrAlternative

Public record (free, scraping required)

SourceWhat it unlocksURL
City of Dallas Open DataBuilding & MEP permits (Socrata API)dallasopendata.com
City of Fort Worth Open DataBuilding & MEP permits (Socrata API)data.fortworthtexas.gov
City of Austin Open DataIssued Construction Permits (Socrata API)data.austintexas.gov
City of San Antonio Open DataBuilding permits datasetdata.sanantonio.gov
Plano, Frisco, McKinney, Arlington, IrvingIndividual permit portalsEach city portal
Round Rock, Cedar Park, GeorgetownAustin metro suburbsEach city portal
TDLRHVAC/R licensing & complaint datatdlr.texas.gov
SEC EDGAR8-K filings announcing new facilitiessec.gov/edgar
Google News RSSPer-account news alertsnews.google.com/rss
Texas ComptrollerCorporate filings, tax status, new business registrationscomptroller.texas.gov
Scraping note: Public portals can be fragile. Dallas, Fort Worth, and Plano all expose Socrata-style APIs (JSON endpoints). For smaller cities, you'll write a scraper + monitoring. Budget a day per city to build and 30 min/month to maintain.

Signal Scoring

Weight each signal type. An account's intent score is the weighted sum of its signals over a 60-day rolling window, with recency decay.

Base Signal Weights

How many points each signal adds to an account's score when detected.

Multipliers

Alert Thresholds

Immediate alert (hot)
80
Daily digest (warm)
50
Weekly report (cool)
20
Scoring formula reference
score(account) = Σ over signals in last 60 days:
    weight(signal_type)
    × topic_match(signal_topic, tracked_topics)
    × tier_multiplier(account.tier)
    × recency_decay(signal.ts)
    × known_contact_boost(account.has_contact ? 1.3 : 1.0)

recency_decay(ts) = exp(-(today - ts) / 30)   // half-life ~21 days

Workflows & Alerts

What happens when a signal fires.

Alert routing

TriggerActionOwner
New permit filed at Tier 1 accountImmediate Slack + SMSSenior BD
Account score crosses hot thresholdImmediate SlackAssigned AE
Known-contact job changeSlack DM + CRM noteOriginal relationship owner
Funding announcement at Tier 1-2 accountSlack + calendar task for follow-up in 2 weeksSenior BD
Site visit from Tier 1 accountSlack notification with pages viewedAssigned AE
Score in warm rangeDaily digest email (8 AM)BD team
Score in cool rangeWeekly digest (Monday 8 AM)BD team

Slack webhook example

// Cloudflare Worker — fires when a signal causes score to cross threshold
async function sendSlackAlert(env, signal, account) {
  const payload = {
    blocks: [
      {
        type: 'header',
        text: { type: 'plain_text', text: `🔥 Intent signal: ${account.name}` }
      },
      {
        type: 'section',
        fields: [
          { type: 'mrkdwn', text: `*Signal:* ${signal.type}` },
          { type: 'mrkdwn', text: `*Topic:* ${signal.topic}` },
          { type: 'mrkdwn', text: `*Score:* ${account.score} (was ${account.prev_score})` },
          { type: 'mrkdwn', text: `*Tier:* ${account.tier}` }
        ]
      },
      {
        type: 'section',
        text: { type: 'mrkdwn', text: `*Detail:* ${signal.detail}` }
      },
      {
        type: 'actions',
        elements: [
          { type: 'button', text: { type: 'plain_text', text: 'Open in CRM' }, url: account.crm_url },
          { type: 'button', text: { type: 'plain_text', text: 'Mark Pursuing' }, value: `pursue_${account.id}` }
        ]
      }
    ]
  };
  await fetch(env.SLACK_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  });
}

Cost Model

Real numbers across three build levels. Without the pixel/IPinfo layer, everything gets cheaper.

Level 1 — Free Tier (Manual Paste) $0-500/yr

This HTML control center (you're using it)Free
Manual form intake via paste-and-parseFree
Google News RSS feeds per accountFree
SEC EDGAR monitoringFree
Manual permit portal checking (Dallas + Austin + SA + FW)Free
LinkedIn Sales Navigator (optional)~$100/mo
Total$0-$1,200/yr

Delivers: form submissions as declared-intent signals, news/expansion alerts, manual permit checks. Good starting point.

Level 2 — Automated (Recommended) $2-5K/yr

Cloudflare Workers + D1 (form parser, permit scraper)Free tier
Cloudflare Email Workers (automated form ingestion)Free tier
Claude/GPT API for parsing + classification$300-600/yr
Permit scraper (Dallas, FW, Austin, SA via Socrata APIs)Free (APIs), ~6 hrs build
Crunchbase Starter API$1,000/yr
Proxycurl LinkedIn lookups (capped)$1,000-2,000/yr
Slack / Resend for alerts$300/yr
Total~$2,500-4,000/yr

Delivers: fully automated form intake, automated permit monitoring, daily news/funding alerts, LinkedIn job-change tracking. This is the sweet spot.

Level 3 — Enterprise $15-25K/yr

Level 2 stack, upgraded tiers$4,000
Coresignal (real-time LinkedIn workforce data)$12,000
ConstructConnect (national construction w/ MEP)$5,000
Crunchbase Enterprise$3,000
Total~$20-24,000/yr

Still under half of ZoomInfo pricing, with better industry+regional tuning.

Recommendation: Start Level 1 today. Costs nothing. The moment you consistently convert one form submission that would have otherwise slipped through, Level 2 pays for itself several times over. Level 3 only makes sense if you need to cover multiple regions at scale.

Export / Backup

All configuration lives in your browser's localStorage. Export regularly.

Export configuration

Downloads a JSON file with all your topics, accounts, scoring weights, and thresholds.

Import configuration

Upload a previously exported JSON file.

Reset everything

Wipes all local data and restores defaults.