mcpField
L
linkedin-outreach

linkedin-outreach

github.com/gooseworks-aiマーケティング・グロース1.3k112 回インストール6 日前に更新
リポジトリ

linkedin-outreach について

linkedin-outreach は、Supabase から適格なリードを選び、LinkedIn メッセージのシーケンスを個別化して、活動を記録するスキルです。ブラウザー型ツールを自動操作せず、選択されたツール向けの CSV を作成します。

主な機能

  1. 01Supabase から対象リードを選択
  2. 02条件と 84 日間のクールダウンを適用
  3. 03個別化したメッセージシーケンスを作成
  4. 04LinkedIn の文字数制限を遵守
  5. 05ツール別の CSV ファイルを出力
  6. 06Supabase に活動を記録

活用シーン

  1. 01適格なリード向け LinkedIn キャンペーンの準備
  2. 02Dripify または Expandi 用のインポートファイル作成
  3. 03複数チャネルで最近連絡したリードの除外
  4. 04Supabase でアウトリーチ活動を記録

MCP 対応

LinkedIn アウトリーチツールの操作に API や MCP 自動化は使わず、手動インポート用の CSV を作成します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gooseworks-ai/goose-skills --skill linkedin-outreach

インストール後、Claude Code で/linkedin-outreachを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

skill.meta.json
templates/
tone-presets.json
templates/sequence-templates/
competitor-engagement.md
database-search.md
event-attendee.md
hiring-signal.md
kol-engagement.md
pain-language.md

詳細

LinkedIn アウトリーチ

cold-email-outreach に対応する LinkedIn 版です。Supabase から条件を満たした見込み顧客を取得し、パーソナライズした LinkedIn メッセージのシーケンスを作成して、ユーザーが使う LinkedIn アウトリーチツール用にエクスポートし、その内容をすべて Supabase に記録します。

ツールに依存しません: 使用している LinkedIn ツールをユーザーに尋ねます。すべてのツールは CSV インポート方式です。LinkedIn ツールはブラウザー上で動作するため、API/MCP による自動化には対応していません。アダプターが、ツールごとの列のマッピングや形式の違いに対応します。

自動読み込みのタイミング

次の場合に、このスキルを読み込みます。

  • ユーザーが「LinkedIn アウトリーチ」「この見込み顧客に LinkedIn でつながる」「LinkedIn メッセージを送る」「LinkedIn キャンペーンを設定する」と言った場合
  • 上流のスキルが「LinkedIn キャンペーンを作成する」と連携する場合、または「supabase-eligible-leads」を渡し、ユーザーが LinkedIn を指定した場合
  • ユーザーが lead-qualification を完了し、LinkedIn で連絡を取りたい場合

対応しているアウトリーチツール

このスキルは特定のツールを前提としません。まずユーザーに尋ねてから、対応します。

ツール連携方法仕組み
DripifyCSV インポートDripify のインポート形式に合わせた CSV を生成し、ユーザーが手動でアップロードします
BotdogCSV インポートBotdog 互換の列を含む CSV を生成します
ExpandiCSV インポートExpandi のインポート形式に合わせた CSV を生成します
PhantomBusterCSV インポートPhantomBuster の LinkedIn シーケンス用 CSV を生成します
手動/その他CSV +手順見込み顧客とメッセージを汎用 CSV としてエクスポートし、設定手順を案内します

ツールの選択ロジック:

  1. フェーズ 0 でユーザーに「どの LinkedIn アウトリーチツールを使っていますか?」と尋ねます
  2. 選択内容に基づき、ツール固有のインポート用 CSV を生成します
  3. その他または不明な場合 → 汎用 CSV(linkedin_url、first_name、last_name、company、title、connection_request、followup_1、followup_2、followup_3、inmail_subject、inmail_body)を生成し、使用するツールのインポート要件をユーザーに尋ねます

前提条件

Supabase

人物データは、tools/supabase/schema.sql のスキーマに従って Supabase に保存されている必要があります。people テーブルと outreach_log テーブルが存在している必要があります。新規にセットアップする場合は、python3 tools/supabase/setup_database.py を実行してください。

.env 内の環境変数:

SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
LinkedIn ツール

CSV をエクスポートするだけでよく、API キーは必要ありません。ユーザーが CSV を手動でツールにインポートします。

文字数制限

LinkedIn には厳格な文字数制限があります。生成するすべてのメッセージは、この制限を守る必要があります。

メッセージの種類制限備考
接続リクエストのメッセージ300 文字厳格な上限です。すべての文字がカウントされます。
通常のメッセージ8,000 文字接続が承認された後に送信されます
InMail の件名200 文字InMail(プレミアム機能)のみ
InMail の本文1,900 文字InMail のみ

制限の適用: メッセージを生成したら、文字数を数えます。上限を超えている場合は、書き直してください。切り詰めてはいけません。切り詰められたメッセージは不自然に見えます。

フェーズ 0:情報の確認

質問はまとめて一度に尋ねます。カテゴリごとに整理してください。上流のスキルですでに回答済みの質問は省略します。

キャンペーンの目標
  1. 目的は何ですか?(面談の予約、デモの申し込み促進、返信の獲得、関係構築、見込み顧客の育成)
  2. アウトリーチの切り口やフックは何ですか?(採用の兆候、競合製品からの乗り換え、イベントをきっかけにする、課題を軸にする、コールドデータベース、KOL とのエンゲージメント、共通の知人)
  3. このキャンペーンにどのような名前を付けますか?
アウトリーチツール
  1. どの LinkedIn アウトリーチツールを使っていますか?(Dripify/Botdog/Expandi/PhantomBuster/その他/CSV だけを作成)
リードの選定
  1. どのリードをターゲットにしますか?次の選択肢があります:
    • 特定の client_name に該当するすべてのリード
    • 特定の icp_segment
    • 役職のパターン(例:「VP Operations」、「Director of Sales」)
    • 業界または所在地によるフィルター
    • qualification_score がしきい値を超えるリード
    • 特定の source(crustdata、apollo、linkedin など)
    • カスタムフィルター(希望する条件を説明してください)
  2. 除外する対象はありますか?(特定の企業、最近連絡したリード、特定の役職など)
  3. キャンペーンの最大規模は?(デフォルト:100 — LinkedIn ツールの1日あたりの上限は、メールより低く設定されています)
トーンとスタイル
  1. どのトーンプリセットを使用しますか?次の選択肢を提示してください:
    • カジュアル・プロフェッショナル — 親しみやすく、人間味があり、ややくだけた表現です。同僚にメッセージを送るような雰囲気です。(デフォルト)
    • ソートリーダー — 洞察や通説に反する見解から始めます。送信者を専門家として位置付けます。
    • 挑発的 — 既成概念に疑問を投げかけ、相手の意表を突きます。リスクもリターンも高くなります。
    • エンタープライズ・フォーマル — 洗練され、構成の整った表現です。規制の厳しい業界や経営幹部層をターゲットにする場合に適しています。
    • カスタム — 以前うまくいった参考メッセージを貼り付けるか、希望する雰囲気を説明してください。
  2. うまくいった参考メッセージはありますか?(例を貼り付けてください。トーンプリセットよりも優先されます)
シーケンスの構成
  1. コネクション後のフォローアップは何回にしますか?(デフォルト:3回)
  2. メッセージ間隔はどのくらいにしますか?(デフォルト:0日目 コネクション/3日目 FU1/7日目 FU2/14日目 FU3)
  3. コネクションを承認しないリード向けに、InMail を別のステップとして含めますか?(デフォルト:はい)
パーソナライズ
  1. これらのリードについて、どのようなシグナルデータを利用できますか?(コメントのテキスト、反応した投稿、共通のつながり、採用シグナル、イベントへの参加)
  2. 参照できる実績や事例はありますか?(顧客名、指標、推薦コメント)

フェーズ 1:Supabase からのリード選定

接続

共有 Supabase クライアントを使用します:

import sys, os
sys.path.insert(0, os.path.join("tools", "supabase"))
from supabase_client import SupabaseClient

client = SupabaseClient(os.environ["SUPABASE_URL"], os.environ["SUPABASE_SERVICE_ROLE_KEY"])
フィルターの作成

ユーザーの条件を people テーブルの PostgREST クエリパラメーターに対応付けます:

ユーザーの指定PostgREST フィルター
「VP Operations」title=ilike.*VP Operations*
クライアント「happy-robot」client_name=eq.happy-robot
スコア > 7qualification_score=gte.7
LinkedIn URL があるlinkedin_url=neq.(空ではない)
業界「logistics」industry=ilike.*logistics*
所在地「San Francisco」location=ilike.*San Francisco*
ソース「crustdata」source=eq.crustdata
84日間連絡していないor=(last_contacted.is.null,last_contacted.lt.{84_days_ago})

重要: LinkedIn でアプローチする場合、対象者には必ず linkedin_url が必要です。LinkedIn URL のない対象者は除外してください。LinkedIn では連絡できません。

クールダウンフィルター(必須)

メールまたは LinkedIn を問わず、いずれかのチャネルで過去84日間に連絡した対象者は必ず除外してください。これは任意ではありません。

共有クライアントの check_cooldown() メソッドを使用します:

in_cooldown = client.check_cooldown(client_name="happy-robot", cooldown_days=84)
# Returns set of person_id strings still in cooldown

または、直接クエリを実行します:

  1. 過去84日間に sent_date がある person_id を outreach_log から取得します:
    GET /rest/v1/outreach_log?select=person_id&sent_date=gte.{84_days_ago}&status=neq.bounced&client_name=eq.{client}
    
  2. それらの person_id を除外セットに追加します
  3. people クエリに id=not.in.({excluded_ids}) を追加します

注: クールダウンはチャネルをまたいで適用されます。30日前にメールを送った対象者は、LinkedIn でも引き続きクールダウンの対象です。これにより、複数チャネルからの過剰な連絡を防ぎます。

表示して確認

サンプルとして、次の項目を含むリードの表を10~15件表示します:

  • 名前、役職、会社、業界、スコア、LinkedIn URL、最終連絡日、シグナルの種類

ユーザーに、対象となるリードの合計数、クールダウンにより除外された数、LinkedIn URL がないために除外された数を伝えます。

先に進む前に、フィルターを確認または調整するようユーザーに尋ねます。

フェーズ 2:シーケンスの設計

コピーを作成する前に、シーケンス案を表にして提示します。

ステップタイミングメッセージの種類アプローチCTA
1Day 0接続リクエスト(300 文字)シグナルに基づくパーソナライズされたメッセージ軽め — まずはつながるだけ
2Day 3フォローアップ 1(承認後)価値を最優先:インサイト、リソース、または所見質問または提案
3Day 7フォローアップ 2ソーシャルプルーフまたは事例具体的な依頼
4Day 14フォローアップ 3最後の連絡いつでも話せることを伝える
5Day 7*InMail(未承認の場合)背景情報を添えた単独の提案面談の依頼

*接続リクエストが Day 7 までに承認されなかったリードに InMail を送信します。

メールシーケンスとの主な違い:

  • 接続リクエストが最初の関門です。承認してもらえる内容にする必要があります。接続メッセージで売り込まないでください。
  • フォローアップは一斉送信ではなく、会話形式にします。メールではなく、DM のように読める内容にしてください。
  • InMail 以外には件名を付けません。
  • 短いほどよい場合がほとんどです。LinkedIn では、5 文のメッセージより 2 文のメッセージのほうが効果的です。

フェーズ 3 でコピーを生成する前に、構成についてユーザーの承認を得ます。

フェーズ 3:メッセージの生成

このスキル内でメッセージを直接生成します(LinkedIn のメッセージは十分短いため、外部のサブスキルは必要ありません)。

シグナルを考慮したテンプレートの選択

リードのシグナルデータに基づいて、適切なシーケンステンプレートを選択します。

シグナルの種類テンプレート主なパーソナライズ変数
悩みの内容に反応したユーザー(コメント文あり)templates/sequence-templates/pain-language.md{comment_snippet}, {pain_topic}
競合他社の投稿に反応したユーザーtemplates/sequence-templates/competitor-engagement.md{competitor_name}, {post_topic}
KOL の投稿に反応したユーザーtemplates/sequence-templates/kol-engagement.md{kol_name}, {post_topic}
データベース検索(シグナルが少ない)templates/sequence-templates/database-search.md{title}, {company}, {industry}
採用シグナルtemplates/sequence-templates/hiring-signal.md{role_hiring_for}, {job_posting_detail}
イベント参加者templates/sequence-templates/event-attendee.md{event_name}, {event_topic}
トーンの調整
  1. templates/tone-presets.json から選択したトーンプリセットを読み込みます
  2. ユーザーが参考メッセージを提供した場合は、プリセットよりもそちらを優先します。参考メッセージのトーン、長さ、構成、語彙を分析してください
  3. トーンのガイドラインを生成するすべてのメッセージに適用します
調整の繰り返し
  1. まず 3~5 件のリード向けにサンプルメッセージを生成します(シグナルの情報量が異なるリードを選んでください)
  2. ユーザーに確認用として提示します。各サンプルリードのシーケンス全体を表示してください
  3. 承認されるまで調整します(最大 3 回)
  4. 承認後に、残りのメッセージをまとめて生成します
ライティングガイドライン

接続リクエスト(最大 300 文字):

  • シグナルから書き始めます(関心を持った相手の行動や発言)
  • 関連性を示す文を 1 つ添えます(なぜつながりたいのか)
  • 売り込み、CTA、「ぜひ~したいです」などは入れません。承認してもらえるほど興味を引く内容にしてください
  • 300 文字未満であることが必須です。すべての文字を数えてください

フォローアップ 1(価値を最優先):

  • つながってくれたことへの感謝を簡潔に伝えます(文全体ではなく、短いフレーズにします)
  • インサイト、記事、相手の会社や業界に関する所見など、本当に役立つ情報を共有します
  • 売り込みではなく、質問で締めくくります

フォローアップ 2(ソーシャルプルーフ):

  • 関連する顧客または事例を紹介します
  • 相手の具体的な状況に結び付けます
  • 具体的で、負担の少ない依頼をします(15 分の通話、非同期での質問など)

フォローアップ 3(最後の連絡):

  • これまで連絡してきたことに触れます
  • 価値を 1 行で振り返ります
  • プレッシャーをかけず、いつでも話せることを伝えます
  • シーケンス中で最も短いメッセージにします

InMail(単独の提案):

  • 件名:最大 200 文字。売り込みではなく、興味を引く内容にします
  • 本文:最大 1,900 文字。接続が承認されていないため、単独で成立する内容にする必要があります
  • 連絡した理由(シグナル)を説明します
  • 相手があなたのことをまったく知らなくても成立する内容にします
マージ変数

すべてのリードで使用できる標準変数:

  • {first_name}、{last_name}、{company}、{title}、{industry}、{location}

ソースに応じて使用できるシグナル固有の変数:

  • {comment_snippet} — LinkedIn のコメント本文
  • {pain_topic} — エンゲージした課題
  • {competitor_name} — 投稿にエンゲージした競合他社
  • {kol_name} — 投稿にエンゲージした KOL
  • {post_topic} — 投稿の内容
  • {event_name} — 参加したイベント
  • {role_hiring_for} — 採用予定の職種
  • {job_posting_detail} — 求人情報の詳細

フェーズ 4:キャンペーンのエクスポート

ステップ 1:汎用 CSV を生成する

すべてのエクスポートに共通する基本列:

linkedin_url, first_name, last_name, company, title, connection_request, followup_1, followup_2, followup_3, inmail_subject, inmail_body
ステップ 2:選択したツールに合わせて形式を整える

Dripify:

  • 列の対応付け:Profile URL → linkedin_url、Note → connection_request、Message 1 → followup_1 など
  • Dripify では、メッセージを別々の列にすべて含め、リードごとに 1 行である必要があります
  • エクスポート形式:Dripify のインポートテンプレートに一致するヘッダーを含む CSV

Botdog:

  • 列の対応付け:linkedin_profile_url → linkedin_url、connection_note → connection_request、message_1 → followup_1 など
  • エクスポート形式:CSV

Expandi:

  • 列の対応付け:LinkedIn URL → linkedin_url、Connection message → connection_request、Follow-up #1 → followup_1 など
  • InMail の列に対応:InMail subject、InMail message
  • エクスポート形式:CSV

PhantomBuster:

  • 列の対応付け:profileUrl → linkedin_url、message → connection_request
  • PhantomBuster では通常、一度に 1 つのアクションを処理するため、コネクションとフォローアップで別々の CSV が必要になる場合があります
  • エクスポート形式:CSV

手動/その他:

  • 汎用 CSV 形式を使用する
  • 列の説明と、ツールに依存しないインポート手順を提示する
  • 使用するツールで必要な形式をユーザーに確認し、必要に応じて調整する
ステップ 3:ファイルを保存する
skills/linkedin-outreach/output/{campaign-name}-{YYYY-MM-DD}.csv

output/ ディレクトリが存在しない場合は作成します。

ステップ 4:Google スプレッドシート(任意)

ユーザーが確認用シートを希望する場合は、google-sheets-write 機能を使って次のシートを作成します:

  • タブ 1:すべてのメッセージを含むリード一覧(リードごとに 1 行)
  • タブ 2:シーケンステンプレート(使用したマスターテンプレート)
  • タブ 3:キャンペーン設定の概要

フェーズ 5:確認と承認

キャンペーンの概要を提示します:

Campaign: {name}
Tool: {dripify/botdog/expandi/etc.}
Leads: {count}
Sequence: Connection + {followup_count} follow-ups + InMail
Timing: Day 0 → Day {last_day}
Tone: {preset_name}
Signal types: {breakdown by signal type}
Leads with rich signal: {count} ({percentage}%)
Leads with lean signal: {count} ({percentage}%)
Export file: {file_path}
必須の承認ゲート

ユーザーから明示的な確認を得るまでは、キャンペーンを準備完了としてマークしないでください。 概要を提示した後、次のように尋ねます:「最終確定しますか?『yes』と入力すると、インポートの準備完了としてマークされます。」

承認後:

  • LinkedIn ツールへのインポート準備が完了したことをユーザーに伝える
  • ファイルパスを提示する
  • ツール固有のインポート手順を案内する(フェーズ 4 を参照)
  • インポート後、最初の 5~10 件のメッセージが正しいことを確認するようユーザーに伝える

フェーズ 6:ログ記録

データベース書き込みポリシー

このフェーズでのデータベースへの書き込みには、すべてフェーズ 5 の最終確定ゲートでユーザーから事前承認を得る必要があります。 LinkedIn キャンペーンは必ずエクスポートされ(自動起動はされません)、ユーザーが LinkedIn ツールにキャンペーンを実際にインポートしていない可能性があるため、outreach_log に記録する前にユーザーに確認してください。ユーザーがエクスポートの最終確定を確認した後にのみ記録します。

Supabase に記録する

エクスポート後、ユーザーの確認を得てから、outreach_log にレコードを挿入します:

POST /rest/v1/outreach_log
Prefer: return=minimal

[
  {
    "person_id": "{person_uuid}",
    "campaign_name": "{campaign_name}",
    "channel": "linkedin",
    "tool": "{dripify/botdog/expandi/phantombuster/manual}",
    "sent_date": "{ISO timestamp}",
    "status": "exported",
    "client_name": "{client_name}"
  },
  ...
]

または、共有クライアントを使用します:

client.log_outreach(entries)

ステータスは "sent" ではなく "exported" です。 LinkedIn ツールはブラウザー上で動作するため、配信を確認できません。ユーザーがツールでキャンペーンを開始したことを確認した時点で、ステータスを "sent" に変更します。

人物レコードを更新する

このキャンペーンに含まれるすべての人物について、people テーブルの last_contacted を更新します:

PATCH /rest/v1/people?id=in.({person_ids})
{ "last_contacted": "{ISO timestamp}" }
概要を提示する
Campaign: {name}
{count} people logged to outreach_log (channel: linkedin)
last_contacted updated for {count} people
Cooldown active until: {date + 84 days}
Next eligible re-contact: {date}
File ready: {file_path}

クールダウン適用ルール

このスキル全体で使用するクールダウンロジックの参照セクションです。cold-email-outreach と共有されています。

ルール詳細
デフォルトのクールダウンsent_date から84日間(12週間)
チャネル間の適用クールダウンはメールと LinkedIn の両方に適用されます。最近メールを送信したリードは、LinkedIn についてもクールダウン中です。
バウンスしたリードクールダウンの対象外です(メールのみ。LinkedIn ではバウンスしません)。クールダウンの確認時のフィルター:status=neq.bounced
進行中のキャンペーンのリード常に対象外です。いずれかのチャネルで進行中のキャンペーンに登録されているリードは、別のキャンペーンに追加できません。
ユーザーによる上書きユーザーは特定のリードについてクールダウンを明示的に上書きできます。許可する前に確認してください。
last_contacted が null の場合連絡したことのないリードは常に対象になります。

出力ディレクトリ

キャンペーンのエクスポートは次の場所に保存されます:

skills/linkedin-outreach/output/

このディレクトリが存在しない場合は作成してください。ファイル名は {campaign-name}-{YYYY-MM-DD}.csv です。

コメント