- 25 LinkedIn profiles → 268 posts → 209 high-engagement posts → 8,855 total engagements, 4,131 senior (49%)
- Run time: ~45–60 minutes end to end
- Cost: ~$20–30 Apify + ~75–150 Deepline credits
When to use
- Building a prospect list for a competitive displacement campaign
- Identifying accounts already evaluating your category
- Finding champions at companies you haven’t penetrated yet
- Researching who your competitors’ most engaged buyers are before a QBR
What you get
| Output | Description |
|---|---|
all_engagements.csv | Every reaction + comment with full engager profile |
senior_engagements.csv | Filtered to VP / CXO / Director / Sales / Marketing |
dashboard.html | Self-contained HTML dashboard — open in browser, shareable |
competitive_analysis.zip | All three files packaged for sharing |
How it works
Why parallel batching? Scraping reactions inline times out every time. The workflow fires async Apify runs in groups of 12, collects dataset IDs as they complete, then downloads all datasets in parallel. This is what makes a 200-post run feasible in under an hour.Invoke in Claude Code
The simplest way to run this — just paste your competitors and go:competitive-social-listening skill to handle the full pipeline — employee discovery, post scraping, parallel reaction batching, senior filtering, and dashboard generation.
Run the script directly
For full runs or to resume a partial run, use the e2e script:CLI commands
CLI commands
Install prerequisitesEstimate cost before runningFull runView results
Input format
Create a seed CSV or pass companies inline usingName:LinkedInURL:domain format:
competitors.csv
Output schema
Both CSVs share the same columns:| Column | Description |
|---|---|
company | Competitor company name |
post_url | LinkedIn post URL |
post_author | Name of the post author |
post_date | When the post was published |
post_total_reactions | Total reaction count on the post |
engagement_type | reaction or comment |
reaction_type | Like, Celebrate, Insightful, etc. |
comment_text | Full comment text (if engagement_type = comment) |
engager_name | Full name of the person who engaged |
engager_linkedin_url | Their LinkedIn profile URL |
engager_position | Current job title |
engager_title_category | C-Suite/Exec, VP, Director, Sales, or Marketing |
is_senior | true / false |
Cost guide
Run this estimate before starting. Always pilot one batch first.| Companies | Employees each | Estimated cost | Deepline credits |
|---|---|---|---|
| 1 | 5 | ~$5–8 | ~25–40 |
| 3 | 10 | ~$20–30 | ~75–150 |
| 5 | 15 | ~$40–60 | ~150–300 |
Known pitfalls
Pitfalls reference (12 documented)
Pitfalls reference (12 documented)
| # | Symptom | Fix |
| --- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------- |
| 1 | 0 employees returned from Dropleads | Use
filters.companyDomains, filters.seniority, pagination.limit (dot notation, not nested objects) |
| 2 | Dropleads JSON parse fails | Response is raw text + CSV path — use re.search(r'(/tmp/\S+\.csv)', output) to extract the path |
| 3 | 0 posts parsed | Field is linkedinUrl not postUrl; engagement is engagement["likes"] not totalReactions |
| 4 | Posts actor 422 error | postedLimit only accepts "month", "3months", "6months", "year" |
| 5 | Employee actor returns empty | harvestapi/linkedin-company-employees is broken — use dropleads_search_people only |
| 6 | Reaction batch exit code 4 | Use async apify_run_actor (not sync) — capture defaultDatasetId, download separately |
| 7 | 2–3 batches timeout when running >15 parallel | Cap at 12 parallel; retry timed-out batches solo (they usually complete on retry in ~15s) |
| 8 | Viral posts (>300 reactions) always timeout | Separate batch: maxReactions: 50, batch size 5 instead of 10 |
| 9 | JSONDecodeError on dataset files | Deepline CLI prepends a status header — skip to first { or [ with re.search(r'(\{ | \[)', content) |
| 10 | Can’t map posts back to companies | source_url is always empty in Apify output — extract handle from linkedinUrl and match against all_urls.csv |
| 11 | SyntaxError: single '}' not allowed in dashboard | JS braces inside Python f-string — use __DATA_JSON__ placeholder + .replace() |
| 12 | _csv.Error: field larger than field limit | Don’t route Apify data through deepline enrich CSV cells — download datasets directly with apify_get_dataset_items |What to do with the output
Highest-intent segment: multi-competitor engagers Filtersenior_engagements.csv for engagers who appear against 2+ competitors — these people are actively evaluating the category.
“Noticed you’ve been following what [Competitor A] and [Competitor B] are building in [category]. We take a different approach — [one sentence differentiator]. Worth a quick conversation?”Next steps after export:
- Run waterfall email enrichment on
senior_engagements.csvto get work emails - Push to HubSpot/Salesforce via MCP as a new “Competitive Engagement” list
- Add to an Instantly / Lemlist sequence with the competitive displacement template above