We Replaced Our $999/Mo Trigify Subscription With $50/Mo of APIs. Here's the System.
LinkedIn engagement tracking. Intent signals. Lead scoring. Trigify does all of it — and charges accordingly. We needed the same data across multiple campaigns but couldn't justify $999/month. So we built our own. Here's the exact stack, scoring logic, cron jobs, and cost breakdown.
---
What Trigify Does (And Why It Works)
Trigify tracks LinkedIn engagement in real-time.
Someone comments on a competitor's post about sales automation? Trigify catches it. A VP at your target account likes three posts about "scaling outbound"? Trigify flags them.
The value: people who engage with relevant LinkedIn content are signaling intent. They're not just scrolling — they're actively thinking about the problem you solve.
We used it. It worked. We were paying $999/month for it.
Then we needed to track multiple ICPs across different campaigns, and the math stopped making sense.
---
Why We Built Our Own
Three reasons:
1. Multi-campaign economics didn't work
We run cold email for clients across different industries. Each campaign needs different engagement signals, different keywords, different scoring logic.
Campaign A: Franchise candidates engaging with business ownership content
Campaign B: Marketing leaders engaging with SEO influencers (Neil Patel, Rand Fishkin)
Campaign C: SaaS buyers engaging with sales automation posts
Trigify's pricing makes sense for one team tracking one ICP. At our scale, we were looking at $999-2,000/month minimum.
2. We needed custom scoring
Trigify gives you the engagement. You decide what it means.
We wanted scoring baked in. Not "this person liked a post" but "this is a 75-point lead because they're a Director-level in our target industry, in our target location, showing ownership interest, with high engagement."
That's custom logic.
3. We were already in the stack
Clay for enrichment. Apify for scraping. Webhooks everywhere. Building LinkedIn tracking into existing infrastructure was less work than another SaaS integration.
---
The System: 4 Components
┌─────────────────────────────────────────────────┐<p dir="ltr">│ LINKEDIN INTENT SYSTEM │</p><p dir="ltr">├─────────────────────────────────────────────────┤</p><p dir="ltr">│ │</p><p dir="ltr">│ [Apify Actor] → [Scoring Engine] → [Clay] │</p><p dir="ltr">│ LinkedIn Post Node.js Script Webhook │</p><p dir="ltr">│ Search + State File + CRM │</p><p dir="ltr">│ │</p><p dir="ltr">│ ↑ │</p><p dir="ltr">│ Cron Job (Daily 7 AM ET) │</p><p dir="ltr">└─────────────────────────────────────────────────┘</p>
┌─────────────────────────────────────────────────┐<p dir="ltr">│ LINKEDIN INTENT SYSTEM │</p><p dir="ltr">├─────────────────────────────────────────────────┤</p><p dir="ltr">│ │</p><p dir="ltr">│ [Apify Actor] → [Scoring Engine] → [Clay] │</p><p dir="ltr">│ LinkedIn Post Node.js Script Webhook │</p><p dir="ltr">│ Search + State File + CRM │</p><p dir="ltr">│ │</p><p dir="ltr">│ ↑ │</p><p dir="ltr">│ Cron Job (Daily 7 AM ET) │</p><p dir="ltr">└─────────────────────────────────────────────────┘</p>
┌─────────────────────────────────────────────────┐<p dir="ltr">│ LINKEDIN INTENT SYSTEM │</p><p dir="ltr">├─────────────────────────────────────────────────┤</p><p dir="ltr">│ │</p><p dir="ltr">│ [Apify Actor] → [Scoring Engine] → [Clay] │</p><p dir="ltr">│ LinkedIn Post Node.js Script Webhook │</p><p dir="ltr">│ Search + State File + CRM │</p><p dir="ltr">│ │</p><p dir="ltr">│ ↑ │</p><p dir="ltr">│ Cron Job (Daily 7 AM ET) │</p><p dir="ltr">└─────────────────────────────────────────────────┘</p>
Component 1: Apify LinkedIn Post Search
We use harvestapi~linkedin-post-search. Feed it queries, get structured post data.
Use Case A — Franchise Candidates:
const SEARCH_QUERIES = [<p dir="ltr">"laid off considering business ownership",</p><p dir="ltr">"severance starting my own",</p><p dir="ltr">"funemployment what's next",</p><p dir="ltr">"tired of corporate want to own",</p><p dir="ltr">"VP laid off",</p><p dir="ltr">"Director position eliminated"</p><p dir="ltr">];</p>
const SEARCH_QUERIES = [<p dir="ltr">"laid off considering business ownership",</p><p dir="ltr">"severance starting my own",</p><p dir="ltr">"funemployment what's next",</p><p dir="ltr">"tired of corporate want to own",</p><p dir="ltr">"VP laid off",</p><p dir="ltr">"Director position eliminated"</p><p dir="ltr">];</p>
const SEARCH_QUERIES = [<p dir="ltr">"laid off considering business ownership",</p><p dir="ltr">"severance starting my own",</p><p dir="ltr">"funemployment what's next",</p><p dir="ltr">"tired of corporate want to own",</p><p dir="ltr">"VP laid off",</p><p dir="ltr">"Director position eliminated"</p><p dir="ltr">];</p>
Use Case B — SEO/Marketing Leaders:
const MONITORED_PROFILES = [<p dir="ltr">{ name: "Neil Patel", username: "neilkpatel" },</p><p dir="ltr">{ name: "Rand Fishkin", username: "randfishkin" },</p><p dir="ltr">{ name: "Alex Hormozi", username: "alexhormozi" }</p><p dir="ltr">];</p><p dir="ltr">// Scrape engagers on their recent posts</p>const MONITORED_PROFILES = [<p dir="ltr">{ name: "Neil Patel", username: "neilkpatel" },</p><p dir="ltr">{ name: "Rand Fishkin", username: "randfishkin" },</p><p dir="ltr">{ name: "Alex Hormozi", username: "alexhormozi" }</p><p dir="ltr">];</p><p dir="ltr">// Scrape engagers on their recent posts</p>const MONITORED_PROFILES = [<p dir="ltr">{ name: "Neil Patel", username: "neilkpatel" },</p><p dir="ltr">{ name: "Rand Fishkin", username: "randfishkin" },</p><p dir="ltr">{ name: "Alex Hormozi", username: "alexhormozi" }</p><p dir="ltr">];</p><p dir="ltr">// Scrape engagers on their recent posts</p>Same infrastructure, different queries.
What Apify returns:
Post content and URL
Author name, title, LinkedIn URL
Engagement metrics (likes, comments, shares)
Post date
Cost: $1-3 per run depending on volume.
Component 2: The Scoring Engine
Raw posts mean nothing. A student posting about their "entrepreneurship journey" isn't a lead. A former VP of Sales posting about their severance package? Gold.
We score every engager/author on multiple dimensions:
Minimum threshold: 20 points.
Director (30) + target industry (20) + ownership interest (25) = 75 points. Qualified.
Random person who mentioned "entrepreneur" once? Maybe 10 points. Filtered out.
Component 3: Exclusion Filters
Equally important — what we DON'T want:
const EXCLUSION_KEYWORDS = [<p dir="ltr">'student', 'intern', 'entry level', 'junior',</p><p dir="ltr">'recent graduate', 'mlm', 'network marketing',</p><p dir="ltr">'crypto', 'bitcoin', 'nft', 'cannabis',</p><p dir="ltr">'we are hiring', 'recruiting for', 'my team is hiring'</p><p dir="ltr">];</p>
const EXCLUSION_KEYWORDS = [<p dir="ltr">'student', 'intern', 'entry level', 'junior',</p><p dir="ltr">'recent graduate', 'mlm', 'network marketing',</p><p dir="ltr">'crypto', 'bitcoin', 'nft', 'cannabis',</p><p dir="ltr">'we are hiring', 'recruiting for', 'my team is hiring'</p><p dir="ltr">];</p>
const EXCLUSION_KEYWORDS = [<p dir="ltr">'student', 'intern', 'entry level', 'junior',</p><p dir="ltr">'recent graduate', 'mlm', 'network marketing',</p><p dir="ltr">'crypto', 'bitcoin', 'nft', 'cannabis',</p><p dir="ltr">'we are hiring', 'recruiting for', 'my team is hiring'</p><p dir="ltr">];</p>
Cuts raw results by 60-70%. That's the point.
Component 4: State Management + Deduplication
Daily runs. Same queries. Without deduplication, duplicates everywhere.
const STATE_FILE = 'data/linkedin-seen.json';<p dir="ltr">// Structure:</p><p dir="ltr">{</p><p dir="ltr">"seen": ["linkedin.com/post/abc123", "linkedin.com/post/def456"],</p><p dir="ltr">"lastRun": "2026-02-15T12:00:00Z"</p><p dir="ltr">}</p>const STATE_FILE = 'data/linkedin-seen.json';<p dir="ltr">// Structure:</p><p dir="ltr">{</p><p dir="ltr">"seen": ["linkedin.com/post/abc123", "linkedin.com/post/def456"],</p><p dir="ltr">"lastRun": "2026-02-15T12:00:00Z"</p><p dir="ltr">}</p>const STATE_FILE = 'data/linkedin-seen.json';<p dir="ltr">// Structure:</p><p dir="ltr">{</p><p dir="ltr">"seen": ["linkedin.com/post/abc123", "linkedin.com/post/def456"],</p><p dir="ltr">"lastRun": "2026-02-15T12:00:00Z"</p><p dir="ltr">}</p>Every processed URL goes into the seen array. Next run skips anything we've seen.
Zero infrastructure. Just a JSON file.
Component 5: Clay Webhook
Qualified, scored, deduplicated leads get pushed to Clay:
const payload = {<p dir="ltr">fullName: lead.author?.name,</p><p dir="ltr">linkedinProfileUrl: lead.author?.linkedinUrl,</p><p dir="ltr">currentTitle: lead.author?.info,</p><p dir="ltr">postText: lead.content?.substring(0, 2000),</p><p dir="ltr">postUrl: lead.linkedinUrl,</p><p dir="ltr">qualityScore: lead._score,</p><p dir="ltr">scoreReasons: lead._scoreReasons.join(', '),</p><p dir="ltr">foundDate: new Date().toISOString().split('T')[0]</p><p dir="ltr">};</p><p dir="ltr">await fetch(CLAY_WEBHOOK_URL, {</p><p dir="ltr">method: 'POST',</p><p dir="ltr">headers: { 'Content-Type': 'application/json' },</p><p dir="ltr">body: JSON.stringify(payload)</p><p dir="ltr">});</p>const payload = {<p dir="ltr">fullName: lead.author?.name,</p><p dir="ltr">linkedinProfileUrl: lead.author?.linkedinUrl,</p><p dir="ltr">currentTitle: lead.author?.info,</p><p dir="ltr">postText: lead.content?.substring(0, 2000),</p><p dir="ltr">postUrl: lead.linkedinUrl,</p><p dir="ltr">qualityScore: lead._score,</p><p dir="ltr">scoreReasons: lead._scoreReasons.join(', '),</p><p dir="ltr">foundDate: new Date().toISOString().split('T')[0]</p><p dir="ltr">};</p><p dir="ltr">await fetch(CLAY_WEBHOOK_URL, {</p><p dir="ltr">method: 'POST',</p><p dir="ltr">headers: { 'Content-Type': 'application/json' },</p><p dir="ltr">body: JSON.stringify(payload)</p><p dir="ltr">});</p>const payload = {<p dir="ltr">fullName: lead.author?.name,</p><p dir="ltr">linkedinProfileUrl: lead.author?.linkedinUrl,</p><p dir="ltr">currentTitle: lead.author?.info,</p><p dir="ltr">postText: lead.content?.substring(0, 2000),</p><p dir="ltr">postUrl: lead.linkedinUrl,</p><p dir="ltr">qualityScore: lead._score,</p><p dir="ltr">scoreReasons: lead._scoreReasons.join(', '),</p><p dir="ltr">foundDate: new Date().toISOString().split('T')[0]</p><p dir="ltr">};</p><p dir="ltr">await fetch(CLAY_WEBHOOK_URL, {</p><p dir="ltr">method: 'POST',</p><p dir="ltr">headers: { 'Content-Type': 'application/json' },</p><p dir="ltr">body: JSON.stringify(payload)</p><p dir="ltr">});</p>From there, Clay handles:
Email enrichment (Apollo, LeadMagic, etc.)
Company enrichment
Verification
Push to CRM or email tool
We're just feeding it high-quality intent signals.
---
The Cron Setup
This runs automatically. No manual intervention.
<h1 dir="ltr">Crontab entry (7 AM ET daily)</h1><p dir="ltr">0 12 <em> </em> <em> cd /path/to/scripts && node linkedin-intent-scraper.js 2>&1</em></p>
<h1 dir="ltr">Crontab entry (7 AM ET daily)</h1><p dir="ltr">0 12 <em> </em> <em> cd /path/to/scripts && node linkedin-intent-scraper.js 2>&1</em></p>
<h1 dir="ltr">Crontab entry (7 AM ET daily)</h1><p dir="ltr">0 12 <em> </em> <em> cd /path/to/scripts && node linkedin-intent-scraper.js 2>&1</em></p>
We use a scheduling system that:
Runs the scraper at 7 AM ET
Processes results through scoring
Pushes to Clay
Reports stats to Slack/Telegram
Actual cron job payload:
Run LinkedIn intent scraper.<ol><li data-preset-tag="p"><p dir="ltr">Execute: node scripts/linkedin-intent-scraper.js</p></li><li data-preset-tag="p"><p dir="ltr">Scoring engine filters to 50+ point leads</p></li><li data-preset-tag="p"><p dir="ltr">Push qualified leads to Clay webhook</p></li><li data-preset-tag="p"><p dir="ltr">Report: raw posts, qualified leads, new leads pushed</p></li></ol>
Run LinkedIn intent scraper.<ol><li data-preset-tag="p"><p dir="ltr">Execute: node scripts/linkedin-intent-scraper.js</p></li><li data-preset-tag="p"><p dir="ltr">Scoring engine filters to 50+ point leads</p></li><li data-preset-tag="p"><p dir="ltr">Push qualified leads to Clay webhook</p></li><li data-preset-tag="p"><p dir="ltr">Report: raw posts, qualified leads, new leads pushed</p></li></ol>
Run LinkedIn intent scraper.<ol><li data-preset-tag="p"><p dir="ltr">Execute: node scripts/linkedin-intent-scraper.js</p></li><li data-preset-tag="p"><p dir="ltr">Scoring engine filters to 50+ point leads</p></li><li data-preset-tag="p"><p dir="ltr">Push qualified leads to Clay webhook</p></li><li data-preset-tag="p"><p dir="ltr">Report: raw posts, qualified leads, new leads pushed</p></li></ol>
Runs daily. Takes 5-10 minutes. Costs $2-5 per run.
---
Multiple Campaigns, Same Infrastructure
The power is running different configs through the same system:
| Campaign | Search Strategy | Scoring Focus | Output |
|----------|-----------------|---------------|--------|
| Franchise Candidates | Keyword search (layoff + ownership) | Title seniority, financial readiness | Clay → EmailBison |
| Marketing Leaders | Influencer engagers (Neil Patel, Hormozi) | CMO/VP Marketing titles only | Clay → Outbound CRM |
| SaaS Buyers | Topic search (sales automation) | SaaS industry, company size | Clay → HubSpot |
Same Apify actor. Same scoring engine. Different config files.
Client config example:
{<p dir="ltr">"name": "Marketing Leaders",</p><p dir="ltr">"monitored_profiles": [</p><p dir="ltr">{ "name": "Neil Patel", "username": "neilkpatel" },</p><p dir="ltr">{ "name": "Alex Hormozi", "username": "alexhormozi" }</p><p dir="ltr">],</p><p dir="ltr">"qualification": {</p><p dir="ltr">"min_score": 50,</p><p dir="ltr">"title_keywords": ["CMO", "VP Marketing", "Head of Marketing"],</p><p dir="ltr">"title_exclude": ["Intern", "Coordinator", "Freelance"]</p><p dir="ltr">},</p><p dir="ltr">"output": {</p><p dir="ltr">"type": "clay_webhook",</p><p dir="ltr">"webhook_url": "https://api.clay.com/v3/sources/webhook/xxx"</p><p dir="ltr">}</p><p dir="ltr">}</p>{<p dir="ltr">"name": "Marketing Leaders",</p><p dir="ltr">"monitored_profiles": [</p><p dir="ltr">{ "name": "Neil Patel", "username": "neilkpatel" },</p><p dir="ltr">{ "name": "Alex Hormozi", "username": "alexhormozi" }</p><p dir="ltr">],</p><p dir="ltr">"qualification": {</p><p dir="ltr">"min_score": 50,</p><p dir="ltr">"title_keywords": ["CMO", "VP Marketing", "Head of Marketing"],</p><p dir="ltr">"title_exclude": ["Intern", "Coordinator", "Freelance"]</p><p dir="ltr">},</p><p dir="ltr">"output": {</p><p dir="ltr">"type": "clay_webhook",</p><p dir="ltr">"webhook_url": "https://api.clay.com/v3/sources/webhook/xxx"</p><p dir="ltr">}</p><p dir="ltr">}</p>{<p dir="ltr">"name": "Marketing Leaders",</p><p dir="ltr">"monitored_profiles": [</p><p dir="ltr">{ "name": "Neil Patel", "username": "neilkpatel" },</p><p dir="ltr">{ "name": "Alex Hormozi", "username": "alexhormozi" }</p><p dir="ltr">],</p><p dir="ltr">"qualification": {</p><p dir="ltr">"min_score": 50,</p><p dir="ltr">"title_keywords": ["CMO", "VP Marketing", "Head of Marketing"],</p><p dir="ltr">"title_exclude": ["Intern", "Coordinator", "Freelance"]</p><p dir="ltr">},</p><p dir="ltr">"output": {</p><p dir="ltr">"type": "clay_webhook",</p><p dir="ltr">"webhook_url": "https://api.clay.com/v3/sources/webhook/xxx"</p><p dir="ltr">}</p><p dir="ltr">}</p>Add a new campaign = add a new JSON file. The system handles the rest.
---
The Cost Breakdown
Real numbers from last month (running 3 campaigns):
| Item | Cost |
|------|------|
| Apify (LinkedIn scraping) | $38 |
| Clay (enrichment credits) | ~$12 (included in existing plan) |
| Infrastructure | $0 (runs on existing server) |
| Total | ~$50 |
Trigify equivalent: $999/month (and that's one campaign)Savings: 95%
---
What This Looks Like Running
Sanitized output from a real run:
==================================================<p dir="ltr">LinkedIn Intent Scraper - Marketing Leaders</p><p dir="ltr">Campaign: influencer-engagers</p><p dir="ltr">==================================================</p><p dir="ltr">🚀 Starting Apify scraper...</p><p dir="ltr">Profiles: Neil Patel, Alex Hormozi</p><p dir="ltr">Posts found: 8 (last 48 hours)</p><p dir="ltr">📊 Scraping engagers...</p><p dir="ltr">Neil Patel post (2.4K likes): 847 engagers scraped</p><p dir="ltr">Alex Hormozi post (1.8K likes): 612 engagers scraped</p><p dir="ltr">Total raw engagers: 1,459</p><p dir="ltr">📊 Scoring results:</p><p dir="ltr">Title match (CMO/VP): 89</p><p dir="ltr">Excluded (students/recruiters): 312</p><p dir="ltr">Below threshold (<50): 847</p><p dir="ltr">Qualified leads: 89</p><p dir="ltr">🆕 New leads (not seen before): 34</p><p dir="ltr">🎯 Top leads to push:</p><p dir="ltr">[82] Sarah Chen - CMO at TechStartup</p><p dir="ltr">Commented: "This is exactly our strategy..."</p><p dir="ltr">[75] Mike Rodriguez - VP Marketing, FinServ Co</p><p dir="ltr">Liked post about content distribution</p><p dir="ltr">[71] Jennifer Park - Head of Marketing, SaaS Inc</p><p dir="ltr">Commented: "Would love to learn more..."</p><p dir="ltr">✅ Pushed 34/34 to Clay</p><p dir="ltr">==================================================</p><p dir="ltr">✅ Complete! 34 qualified marketing leaders</p><p dir="ltr">==================================================</p>
==================================================<p dir="ltr">LinkedIn Intent Scraper - Marketing Leaders</p><p dir="ltr">Campaign: influencer-engagers</p><p dir="ltr">==================================================</p><p dir="ltr">🚀 Starting Apify scraper...</p><p dir="ltr">Profiles: Neil Patel, Alex Hormozi</p><p dir="ltr">Posts found: 8 (last 48 hours)</p><p dir="ltr">📊 Scraping engagers...</p><p dir="ltr">Neil Patel post (2.4K likes): 847 engagers scraped</p><p dir="ltr">Alex Hormozi post (1.8K likes): 612 engagers scraped</p><p dir="ltr">Total raw engagers: 1,459</p><p dir="ltr">📊 Scoring results:</p><p dir="ltr">Title match (CMO/VP): 89</p><p dir="ltr">Excluded (students/recruiters): 312</p><p dir="ltr">Below threshold (<50): 847</p><p dir="ltr">Qualified leads: 89</p><p dir="ltr">🆕 New leads (not seen before): 34</p><p dir="ltr">🎯 Top leads to push:</p><p dir="ltr">[82] Sarah Chen - CMO at TechStartup</p><p dir="ltr">Commented: "This is exactly our strategy..."</p><p dir="ltr">[75] Mike Rodriguez - VP Marketing, FinServ Co</p><p dir="ltr">Liked post about content distribution</p><p dir="ltr">[71] Jennifer Park - Head of Marketing, SaaS Inc</p><p dir="ltr">Commented: "Would love to learn more..."</p><p dir="ltr">✅ Pushed 34/34 to Clay</p><p dir="ltr">==================================================</p><p dir="ltr">✅ Complete! 34 qualified marketing leaders</p><p dir="ltr">==================================================</p>
==================================================<p dir="ltr">LinkedIn Intent Scraper - Marketing Leaders</p><p dir="ltr">Campaign: influencer-engagers</p><p dir="ltr">==================================================</p><p dir="ltr">🚀 Starting Apify scraper...</p><p dir="ltr">Profiles: Neil Patel, Alex Hormozi</p><p dir="ltr">Posts found: 8 (last 48 hours)</p><p dir="ltr">📊 Scraping engagers...</p><p dir="ltr">Neil Patel post (2.4K likes): 847 engagers scraped</p><p dir="ltr">Alex Hormozi post (1.8K likes): 612 engagers scraped</p><p dir="ltr">Total raw engagers: 1,459</p><p dir="ltr">📊 Scoring results:</p><p dir="ltr">Title match (CMO/VP): 89</p><p dir="ltr">Excluded (students/recruiters): 312</p><p dir="ltr">Below threshold (<50): 847</p><p dir="ltr">Qualified leads: 89</p><p dir="ltr">🆕 New leads (not seen before): 34</p><p dir="ltr">🎯 Top leads to push:</p><p dir="ltr">[82] Sarah Chen - CMO at TechStartup</p><p dir="ltr">Commented: "This is exactly our strategy..."</p><p dir="ltr">[75] Mike Rodriguez - VP Marketing, FinServ Co</p><p dir="ltr">Liked post about content distribution</p><p dir="ltr">[71] Jennifer Park - Head of Marketing, SaaS Inc</p><p dir="ltr">Commented: "Would love to learn more..."</p><p dir="ltr">✅ Pushed 34/34 to Clay</p><p dir="ltr">==================================================</p><p dir="ltr">✅ Complete! 34 qualified marketing leaders</p><p dir="ltr">==================================================</p>
1,459 engagers scraped.
312 excluded immediately (wrong titles).
847 scored too low.
89 qualified.
34 were new.
Those 34 leads are now in Clay, getting enriched, ready for outreach.
Tomorrow, same process. New posts. New engagers. Compounding intent data.
---
The Limitations (When to Just Pay for Trigify)
What we gave up:
Real-time monitoring. We run daily. Trigify watches continuously. If you need to jump on engagement within hours, Trigify wins.
Engagement on specific posts. We search for keywords or scrape influencer engagers. Trigify can monitor engagement on YOUR specific post. Different capability.
Maintenance. Apify actors change. LinkedIn's structure changes. We've fixed the scraper twice in six months. Trigify handles that.
UI/reporting. We're looking at JSON and Clay dashboards. Trigify has purpose-built analytics.
When Trigify makes sense:
Single ICP, single team
Need real-time alerts
Want to monitor your own posts
Don't have existing Clay infrastructure
Engineering time > subscription cost
When DIY makes sense:
Multiple ICPs or client campaigns
Custom scoring logic needed
Already have Clay/enrichment workflows
Volume economics favor API costs
Comfortable maintaining scripts
---
How to Build This
Step 1: Apify setup
Sign up at apify.com. Actor: harvestapi~linkedin-post-search. Test with a few queries manually.
Step 2: Define scoring logic
What makes someone a lead for YOU?
Target titles
Target industries
Intent keywords
Disqualifiers
Step 3: Clay webhook
Create "Pull in data from webhook" source in Clay. You get a URL. That's your destination.
Step 4: Write the glue
Node.js script:
Call Apify with queries
Score each result
Filter to qualified leads
Dedupe against state file
POST to Clay webhook
~250 lines of code. Not complicated.
Step 5: Schedule it
Cron job. GitHub Actions. Whatever you use. Daily is usually enough.
---
The Takeaway
Trigify is a good product. We used it.
But at $999/month for one campaign, the math didn't work when we needed to track franchise candidates, marketing leaders, and SaaS buyers simultaneously.
Same infrastructure, three campaigns: $50/month total.
The code isn't complicated. The logic isn't proprietary. The infrastructure is commodity.
Sometimes "we can build this" is the right answer.
---
We run cold email infrastructure for B2B companies. If you want leads (not LinkedIn scrapers), that's what we actually sell: buzzlead.io*