apify-lead-scoring-enrichment について
会社 URL の CSV から、スコアと連絡先情報を付けたリードを作成するワークフロースキルです。技術スタック、ウェブサイトの内容、企業メタデータを使って評価し、しきい値で絞り込んでから情報を補完します。
主な機能
- 01CSV の入力と検証
- 02技術・コンテンツ・メタデータの評価
- 03ユーザー定義の評価ルール
- 04適格しきい値による絞り込み
- 05部署担当者または著者の情報補完
- 06情報を統合した CSV の出力
活用シーン
- 01独自の適合ルールで企業リードを優先順位付け
- 02適格企業の部署担当者を探す
- 03ブログ著者からゲスト投稿の連絡先リストを作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ apify/ awesome-skills --skill apify-lead-scoring-enrichmentインストール後、Claude Code で/apify-lead-scoring-enrichmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignoreexamples/leads.example.csvscoring-rules.example.mdreferences/actor-index.mdgotchas.mdscripts/apify_client.jsenrich_copywriters.jsenrich_departments.jsfilter_qualified.jsmerge_output.jspackage.jsonrun_scoring.js詳細
リードのスコアリングとエンリッチメント
会社の URL をまとめた CSV を、スコアを付け、連絡先情報を補完した営業リストに変換します。エージェントはユーザーに平易な英語でスコアリングルール(「Shopify を使用している場合は +10」「従業員数が 10 人未満の場合は -5」)を尋ね、エンリッチメントの方法(部門またはコピーライター)を選択し、4 つのヘルパースクリプトを通じて 6 つの Apify Actors を連携させます。
前提条件
- 有効な
APIFY_TOKENが設定された Apify アカウント(Console → Settings → Integrations) - Node.js 20.6 以降(ネイティブの
--env-fileサポートが必要です) - スキルのルートに
APIFY_TOKEN=apify_api_...を含む.envファイル scripts/内で一度だけ実行:npm install(csv-parse、csv-stringifyをインストールします)
任意ですが、アドホックな Actor 呼び出しには Apify CLI(npm i -g apify-cli)の使用をおすすめします。ヘルパースクリプトは REST API を直接呼び出すため、CLI は必要ありません。
ワークフロー
このチェックリストをコピーして、進捗を記録してください。
Task Progress:
- [ ] Step 1: Collect CSV path and validate required column (company_url)
- [ ] Step 2: Collect scoring rules per source (tech / content / metadata)
- [ ] Step 3: Collect enrichment path (departments OR copywriters)
- [ ] Step 4: Run scoring Actors (writes scoring.json)
- [ ] Step 5: Apply scoring rules per lead → assign per-source scores + outreach_hook (writes scored.json)
- [ ] Step 5b: Compute theoretical min/max score, ask user for qualification threshold, filter leads → qualified_leads.csv
- [ ] Step 6: Run enrichment path against qualified_leads.csv (writes enrichment.json)
- [ ] Step 7: Merge scoring + enrichment onto the ORIGINAL CSV → leads.enriched.csv (qualified column marks who made the cut)
ステップ 1:CSV の受け取り
ユーザーに CSV のパスを尋ねます。必須の列は company_url です。認識される任意の列はそのまま引き継がれます:company_name、first_name、last_name、role、department。company_url がない場合は処理を中止してください。ドメインを要求する後続の Actor に渡す際は、URL をドメインのみの形式に整えます(末尾のスラッシュを削除し、www. は任意です)。
ステップ 2:スコアリングルール(データソース別)
ユーザーにデータソースごとに 1 つ質問し、それぞれのルールがどのデータを対象とするかをユーザーにも自分にも(ステップ 5 で)明確にします。ユーザーが取得を希望するデータソースについてのみ質問してください。各データソースにはステップ 4 の対応する --enable-* フラグがあります。
2a. テクノロジースタックのルール — scoring.json[url].tech(BuiltWith の出力)に対して適用します。ユーザーが --enable-tech を希望する場合のみ質問してください。次のルール例を提示します:
- 会社が Shopify または WooCommerce を使用している場合は +10(Shopify 統合を販売しているため)。
- テクノロジースタックに HubSpot、Marketo、または Segment が含まれる場合は +5(マーケティングオペレーションの ICP)。
- 分析ツールまたは CDP が検出されない場合は -3(まだ初期段階すぎる可能性があります)。
2b. ウェブサイトコンテンツのルール — scoring.json[url].content(Website Content Crawler のマークダウン/テキスト)に対して適用します。ユーザーが --enable-content を希望する場合のみ質問してください。ここで maxCrawlDepth も尋ねます(デフォルトの 0 はホームページのみ、高い値ほどコストがかかります)。ルール例:
- ホームページで SaaS またはプラットフォーム事業について説明している場合は +8。
- ホームページでサービス提供会社について説明している場合は -5(対象となる ICP ではありません)。
- ホームページに「developers」または「API」という語が含まれる場合は +3(技術系の購入者)。
2c. 企業メタデータのルール — scoring.json[url].metadata(Contact Info Scraper のメタデータ)に対して適用します。ユーザーが --enable-metadata を希望する場合のみ質問してください。ルール例:
- 業界が e コマース、小売、または B2C の場合は +3。
- 従業員数が 10 人未満の場合は -3(購入するには規模が小さすぎます)。
- 会社が LinkedIn 上に存在する場合は +5(より規模の大きな事業)。
各ルールのまとまりは、データソースのタグを付けて、原文のまま保存します。ユーザーがメタデータのルールをテクノロジーのまとまりに含めた場合(例:「テクノロジー」の下に「規模が 50 人を超える場合は +3」)、ステップ 5 の前に正しいまとまりへ移し、その理由を説明してください。
ユーザーがルールを設定していないデータソースは、ステップ 4 の --enable-* フラグからも外してください。スコアリングしないシグナルに料金を払う意味はありません。ルールセットの詳しい例は、examples/scoring-rules.example.md を参照してください。
ステップ 3:エンリッチメントの方法(いずれかを選択)
質問します:「どのエンリッチメント方法にしますか?
- (A) 部門の連絡先 — 各企業の特定のチームに所属する、氏名(役職+メールアドレス付き)が分かる人を見つけます。Contact Info Scraper の「Business leads enrichment」アドオンを使用し、メールアドレスが見つからなかったリードには Bulk Email Finder を使用します。
- (B) コピーライターの調査 — 各ドメインについて、Google で
site:{domain} blogを検索し、上位の投稿から著者名を抽出して、メールアドレスを見つけます。ゲスト投稿のアウトリーチに適しています。」
方法 A の場合は、さらに 2 つの入力を収集します。
- 部門 — 次の列挙値から 1 つ以上を選択(カンマ区切り):
c_suite、product、engineering_technical、design、education、finance、human_resources、information_technology、legal、marketing、medical_health、operations、sales、consulting。 例:marketing,sales。 - ドメインあたりのリードの最大数 — 整数。一般的な SDR 業務では 3~5 を推奨します。
⚠️ これはコスト倍率です。5 件のリード × 500 ドメイン = 最大 2500 件の
課金対象リードになります。Apify は正常に見つかったリードにのみ課金します。
max_leads × domain_count > 500の場合、実行前にユーザーへ警告してください。
方法 B の場合、追加の入力は必要ありません。
ステップ 4:スコアリング Actor を実行する
node --env-file=.env scripts/run_scoring.js \
--input leads.csv \
--output scoring.json \
--enable-tech --enable-content --enable-metadata \
--content-crawl-depth 0
run_scoring.js は、有効な Actor ごとにすべての URL を 1 回の呼び出しにまとめます(リードごとに
1 回ではありません)。その後、データセットを URL ごとのサイドカーに整形し、
エージェントが company_url で各シグナルを参照できるようにします。
--enable-* が指定されていない Actor はスキップされます。生成された scoring.json を読み込みます。
その形式は { "https://acme.com": { "tech": {...}, "content": {...}, "metadata": {...} }, ... } です。
ステップ 5:スコアリングルールを適用する(ソースごとに適用してから合計)
scoring.json 内の各リードについて、ステップ 2 の該当ソースのルールのみを使用して、
ソースごとに 1 回適用します。これによりスコアを監査可能な状態に保てます。たとえば、
コンバージョンするとユーザーが予想していたリードの content_score = -5 の場合、
計算全体をやり直さなくても、どのコンテンツルールが適用されたのかを正確に確認できます。
リードごとに次の 5 つのフィールドを作成します。
tech_score(数値、または--enable-techがオフの場合はnull)—scoring.json[url].techに対する ステップ 2a のルール差分の合計。content_score(数値、または--enable-contentがオフの場合はnull)—scoring.json[url].contentに対するステップ 2b のルール差分の合計。metadata_score(数値、または--enable-metadataがオフの場合はnull)—scoring.json[url].metadataに対するステップ 2c のルール差分の合計。score(数値)— 上記 3 つの合計。nullは0として扱います。outreach_hook(文字列、1 文)— すべてのソースの中で、最も個別化しやすいシグナルを 1 つ選びます。 特定の CMS(「Shopify を使用」)、名前が判明している分析ツール、業界の一致、文章内の採用シグナルなど、 営業担当者がメールの書き出しに使うようなものを選びます。
null と 0 の違いは重要です。取得されなかったソースを、取得されたもののスコアが単に 0 だった
ソースと混同してはいけません。後続の CSV 列では、null は空欄、0 は "0" として出力されます。
スコア付けした行を中間ファイル scored.json として保存します(エージェントが正規化された
https://domain をキーにして直接書き込みます)。その後、ステップ 5b で filter_qualified.js に、
ステップ 7 で merge_output.js に渡します。
ステップ 5b:適格性のしきい値ゲート
エンリッチメントはコストがかかる処理です。適格でないリードに実行すると、ROI が得られないままクレジットを消費します。エンリッチメント Actor を呼び出す前に、ユーザーが設定したしきい値で絞り込みます。
-
ステップ 2 でユーザーが指定したルールから、理論上のスコア範囲を算出します。 各ソースのルールセットについて、正の差分をすべて
max_sourceに、負の差分をすべてmin_sourceに合計します。次に、min_total = min_tech + min_content + min_metadataと同様にmax_totalを算出します。これはハード上限です。この範囲を外れるスコアのリードはありません。 -
scored.jsonから実測範囲も算出します。 すべてのリードにおけるscore値の実際の最小値と最大値です。多くの場合、実測範囲は理論上の範囲よりかなり狭くなります。 -
両方の範囲と、おおよそのランク分けの提案をユーザーに提示します。
「理論上の範囲:{min_total}~{max_total}。リスト内の実測範囲:{observed_min}~{observed_max}({n_leads} 件のリード)。分布:各しきい値での 75 パーセンタイル以上/50 パーセンタイル以上/25 パーセンタイル以上の件数は {count above 75th percentile} / {count above 50th percentile} / {count above 25th percentile} です。どのしきい値にしますか?しきい値以上のスコアのリードはエンリッチメントに進み、それ未満のリードは最終 CSV で
qualified=falseとしてマークされ、スキップされます。」ユーザーが迷っている場合は、開始点として 75 パーセンタイルのスコアを推奨します。ファネル上位を維持しながら、エンリッチメントのコストを約 75% 削減できます。選択したしきい値で適格なリードが 0 件になる場合、またはすべてのリードが適格になる場合(フィルタリングされない場合)は、注意を促します。
-
選択したしきい値に基づいて、
scored.jsonのすべての行にqualified: true|falseを付けて(ファイルに書き戻してから)、次を実行します。node scripts/filter_qualified.js \ --leads leads.csv \ --scores scored.json \ --output qualified_leads.csvfilter_qualified.jsは純粋な Node.js 製 CSV フィルターです。scored.jsonを読み込み、qualified === trueの行だけを残して、元のすべての列を保持したままqualified_leads.csvに書き込みます。未適格の行を含む全リードのリストは元のleads.csvに残ります。ステップ 7 のマージでは、これを結合のベースとして使用します。
ステップ 6:エンリッチメントの処理を実行する(適格なリードのみ)
元の leads.csv ではなく、ステップ 5b の qualified_leads.csv をエンリッチメントのスクリプトに渡します。ここでしきい値ゲートの効果が得られます。
パス A — 部門の連絡先:
node --env-file=.env scripts/enrich_departments.js \
--input qualified_leads.csv \
--department marketing,sales \
--max-leads 5 \
--output enrichment.json
返されたメールアドレスもすべて検証する場合は、--verify-emails を追加します(検証済み/無効/使い捨ての結果ごとに少額の追加料金がかかります。Actor のドキュメントによると、キャッチオールと不明は無料です)。
パス B — コピーライターの調査:
node --env-file=.env scripts/enrich_copywriters.js \
--input qualified_leads.csv \
--output enrichment.json
パス A は vdrmota/contact-info-scraper を、ビジネスリードのエンリッチメントアドオン(maximumLeadsEnrichmentRecords と leadsEnrichmentDepartments)を有効にして呼び出します。これにより、Actor はドメインごとに実際の人物(氏名、役職、勤務先メールアドレス、LinkedIn)を返します。メールアドレスが特定できなかったリードについては、スクリプトがフォールバックとして (firstName, lastName, domain) の組み合わせで scalelist/email-finder を呼び出します。パス B は apify/google-search-scraper → apify/ai-web-scraper(get-author-name-from-blog-post の入力例を使用)→ scalelist/email-finder の順に実行します。
ステップ 7:マージ
node scripts/merge_output.js \
--leads leads.csv \
--scoring scoring.json \
--enrichment enrichment.json \
--scores scored.json \
--output leads.enriched.csv
--leads は qualified_leads.csv ではなく、元の leads.csv であることに注意してください。これにより、すべての入力リードが最終 CSV に含まれます。条件を満たさないリードは、エンリッチメント列が空欄になり、qualified=false となるだけです。これにより監査証跡が保たれ、どのリードがしきい値を下回ったのか、その理由を確認できます。
merge_output.js は純粋な Node で動作し、Actor 呼び出しはありません。company_url をキーに左外部結合し、元の列に加えて次の列を含む leads.enriched.csv を出力します。
tech_summary、content_summary、company_size、industry、
tech_score、content_score、metadata_score、score(合計)、
qualified(true / false — ステップ 5b のしきい値に一致)、outreach_hook、
leads(Path A で見つかったドメインごとの人物情報を完全な JSON 形式で格納)、
lead_names と lead_titles(CSV で読みやすいよう、セミコロン区切りの概要)、
emails(セミコロン区切り)、および authors(Path B)。
Actor のルーティング
| ユーザーの意図 | Actor | ティア | 備考 |
|---|---|---|---|
| 技術スタックの検出 | builtwith/builtwith-official-technology-scraper | community | 入力:{ "startDomains": ["acme.com", ...] }(ドメインのみ。プロトコルは不要)。CMS、分析、ホスティングの情報はアプローチのきっかけになります。 |
| ウェブサイトコンテンツの分類 | apify/website-content-crawler | apify | ホームページのみを対象にするには maxCrawlDepth: 0 に設定します。値を大きくするとコストが増えます。 |
| 企業メタデータ(スコアリングパス) | vdrmota/contact-info-scraper | community | アドオンはオフにします。About / Contact ページから、メールアドレス、電話番号、ソーシャル情報、企業メタデータを取得します。 |
| 部門別リード(Path A のエンリッチメント) | vdrmota/contact-info-scraper | community | maximumLeadsEnrichmentRecords と leadsEnrichmentDepartments(列挙型)を使ってアドオンをオンにします。実際の人物情報として、氏名、役職、業務用メールアドレス、LinkedIn を取得します。 |
| ブログの検出 | apify/google-search-scraper | apify | クエリは site:{domain} blog、resultsPerPage: 5 にします。 |
| ブログ著者の抽出 | apify/ai-web-scraper | apify | get-author-name-from-blog-post の例を使用します。 |
| メールアドレス検索のフォールバック | scalelist/email-finder | community | 入力:{ "leads": [{ "first_name", "last_name", "company_domain" }] }。氏名はあるもののメールアドレスがないリードに対してのみ呼び出されます。 |
入力スキーマと注意点の詳細については、references/actor-index.md を参照してください。
Actor の呼び出し — CLI の手順
apify CLI の呼び出しには、すべて 3 つのフラグを指定する必要があります(CI で強制されています)。
apify actors call ACTOR_ID \
-i 'JSON_INPUT' \
--user-agent apify-awesome-skills/apify-lead-scoring-enrichment \
--json 2>/dev/null
apify actors info ACTOR_ID --input \
--user-agent apify-awesome-skills/apify-lead-scoring-enrichment \
--json 2>/dev/null
apify datasets get-items DATASET_ID \
--user-agent apify-awesome-skills/apify-lead-scoring-enrichment \
--format json 2>/dev/null
ヘルパースクリプトは REST API を直接使用し、すべてのリクエストに同じ apify-awesome-skills/apify-lead-scoring-enrichment ユーザーエージェントヘッダーを設定するため、CLI とスクリプトのどちらを使って実行しても、アトリビューションは一貫します。
代替インターフェース
- Apify MCP connector — https://mcp.apify.com(ドキュメント)。ヘルパースクリプトを使わず、エージェントが Actor を MCP ツールとして呼び出します。
- mcpc — スタンドアロンの MCP クライアント。https://github.com/apify/mcpc。
ヘルパースクリプトを使わない場合でも、ステップ 5 のスコアリングロジックを自分で適用し、最終 CSV を作成する必要があります。
トラブルシューティング
APIFY_TOKEN not set— スクリプトは.envからnode --env-file=.env経由で読み込みます。.envがスキルのディレクトリではなく、cdで移動したディレクトリにあることを確認してください。絶対パスを使うと便利です:node --env-file=/abs/path/.env scripts/...。- Node <20.6 で
fetch failedが発生する —--env-fileには 20.6 以降が必要です。node --versionで確認してください。アップグレードするか、シェルでAPIFY_TOKENを手動でエクスポートしてください。 - BuiltWith が URL に対して空の結果を返す — ドメインに接続できない、WAF にブロックされている、または新しいドメインで過去の検出データがありません。完全な URL ではなく、ドメインのみ(
acme.com)を渡して、失敗した行だけを再試行してください。 - Contact Info Scraper がドメインのリードを 0 件返す — ドメインが Actor に組み込まれた除外リスト(大規模チェーン、ソーシャルプラットフォーム、小売大手、フードデリバリーサービス)で除外されているか、指定した部門に見つけられる従業員がサイトにいません。より広い部門を試す(例:
marketingとあわせてc_suiteを追加する)か、そのセグメントではコピーライターの経路に切り替えてください。 - リードに名前はあるがメールアドレスがない — Business-Leads アドオンで解決できませんでした。パス A は
(firstName, lastName, domain)を使ってscalelist/email-finderに自動でフォールバックします。フォールバックでも何も返らない場合、その人物のメールアドレスは Scalelist のインデックスに実際に存在しません。LinkedIn Sales Navigator で手動検索するか、その行を削除してください。 - コピーライターの経路でドメインの著者が 0 人返される — そのドメインにブログがないか、ブログ記事に著者名が表示されていません。その行はスキップしてください。そのドメインにはゲスト投稿のアウトリーチは適切ではありません。
- 実行中に Apify クレジットが不足した —
run_scoring.jsv1 では部分的な復旧はできません。CSV の小さな範囲に絞って再実行してください。Actor ごとの費用見積もりについては、references/gotchas.md を参照してください。