マーケティングオペレーション・アズ・コード:GitHubで計画からフォローアップまでのキャンペーンを自動化
GitHub のマーケティングチームは Issue forms、Labels、Actions を使ってイベント準備を自動化し、これまで手作業で2〜3日かかっていた作業が1つの Issue で自動構築、毎日の申し込み確認、締めくくりまでできるようになった。
日本語
コピー

日本と韓国で GitHub のマーケティングを担当していて、イベントはその仕事の中心だ。企業開発者向けのウェビナーシリーズ、東京でのコミュニティミートアップ、ソウルでの招待制エグゼクティブクローズドセッション。この市場の開発者が今ほんとうに必要としているものは何か。1時間を割く価値のあるテーマはどれで、誰を呼ぶべきか。そんなことを一日中考えていられる。
決まったあとのことは、また別の話だ。イベントが承認されると、決まった手順が動き出す。
- イベントプラットフォームでランディングページを複製する。
- UTM パラメータ付きのリンクを一式生成する。チャネルごとに1本、フォーマットにも決まりがある。
- 招待メールを下書きし、送信担当チームに申請を出す。
- プロジェクトボード2つにイベントを追加する。
- 開催前は毎朝、登録者リストをダウンロードしてデータをクレンジングし、関係者にステータスを1本送る。
- 開催後は、参加者リストをエクスポートし、CRM にアップロードできる形式に整え、該当レコードにタグを付け、レポートを書く。
一つひとつは難しくない。だがどのステップでも、リンクを貼り間違えたり、1日飛ばしたり、campaign 名を打ち間違えたりする余地がある。しかも下流では15本のレポートがそれに依存している。
問題は、僕が元エンジニアだということだ。最初の職は Linux サーバー上で企業顧客のデータベースを保守する仕事だった。コードを書く勘は鈍ったかもしれないが、どのパイプラインが自動化されるのを待っているかは今でも一目でわかる。そこで GitHub Copilot の出番になる。あなたも自分の仕事で同じことができる。
コードは僕が書いたわけではない。自分の手順書を書き出し、GitHub Copilot に渡して、対話しながら自動化を少しずつ組み上げていった。今では、以前なら手作業で2、3日かけて準備していたイベントが、GitHub Issue 一つで勝手に組み上がり、毎朝登録者をスクリーニングし、終われば自分で後片付けまでする。
この記事では、それがどう動いているのか、そしてなぜ僕が、複数のツール間で繰り返し作業をしていて、それらのツールにスクリプトから叩ける入口(API、あるいは CLI だけでも)があるなら誰でも同じことができると考えているのかを説明する。
イベントとは issue である
この基本アイデアは僕が考えたものではない。GitHub のマーケティングチームはもともと、プロジェクトごとに GitHub Issue を立てる習慣があった。計画も議論もステータスもここに集まる。Issue はすでに僕たちの仕事の基本単位だった。僕がやったのは、issue 自身に働かせることだ。
システムを支えているのは GitHub の3つのプリミティブだ。
- Issue forms は申請書。 issue form は空白のテキストボックスではなく、構造化されたフィールドを表示する。イベント名、日付、地域、campaign 名、対象オーディエンス。イベント種別ごとに1つのフォームがあり、たとえばウェビナーとオフラインイベントは同じ仕組みにつながっている。
- Labels はスイッチ。
event-setupのようなラベルは分類マークではなくトリガーだ。どの自動化ワークフローも条件から始まり、その意味は「このラベルがあるときだけ動く」。 - Actions は機械。 ラベルが付いた瞬間に GitHub Actions ワークフローが起動し、issue 本文からフォームのフィールドを解析して、仕事をこなす。
リポジトリが開発者に与えているものは、僕のマーケティングワークフローにも無料でそのまま与えられている。履歴、可視性、レビュー、そしてあらゆる決定に対応する1つの URL。
これを可能にした要素が一つあり、それはイベントとは何の関係もない。イベント管理プラットフォームに API があることだ。CRM には API すら要らなかった。公式 CLI が僕たちの操作をすべてカバーしていて、API キーを設定したこともない。CLI がブラウザ経由でログインし、認証は自分で処理してくれるからだ。API でも CLI でも、要求されることは同じ。スクリプトから叩ける入口が1つあればいい。繰り返し作業が、イベントプラットフォーム、CRM、フォームビルダー、分析サービスのいずれかの上で動いているなら、この記事のパターンはあなたにも当てはまる。
ここまで読んだ開発者は、おそらくあの当然の反論を組み立てているはずだ。これって車輪の再発明では? マーケティングオートメーションプラットフォームは既にあるし、うまく使えばその一部はそのままカバーできる。だが APAC は一つの市場というより、大きく性格の異なる市場の寄せ集めで、僕のチームの中ですらワークフローはサブリージョンごと、セグメントごとに変わる。同じウェビナーでも、今月は東京向けに日本語で、来月はソウル向けに韓国語で開催することがあり、セグメントが違えば CRM のフィールドも違い、優良リードの定義も違う。パッケージ製品にこの差を全部飲み込ませようとすれば、カスタマイズ予算、コンサル工数、そして他人の roadmap を待つ時間が発生する。自分でやる、手元にあるツールでやるとなれば、ワークフローの変更は1本の pull request で済む。欲しいものを説明し、レビュアーが確認し、main にマージされる。開発者がソフトウェアを変更するときと同じ流れだ。
イベントの企画は対話である
パイプラインは Issue ができる前から動き出している。GitHub Copilot を開いて、こんなふうに話しかける。「11月に AI 支援開発をテーマにしたウェビナーをやりたい」。
そこで何が起きるかを決めるのは AGENTS.md というファイルで、リポジトリのルートに置いてある。チームの手順書をプレーンな Markdown で書いたもので、イベントの命名規則、会計四半期と具体的な日付の対応、地域ごとのタイムゾーン、そして合格ラインを満たす招待メールの形が定めてある。GitHub Copilot はそれを読み、過去の類似イベントを見つけ、僕たちの命名規則に沿ったイベント名を提案し、招待メールを2案下書きし、手順書が答えを求める質問を僕に投げてくる。
会話をパイプラインの最上流に置くこと自体が一つの設計判断であり、それだけで二つの問題が同時に片づく。すべてを自動化すれば柔軟性を失う。あるイベントだけ少し変えたいと思っても、硬直したパイプラインにはそれを表現する場所がない。かといってすべてを手作業で埋めれば、ミスが出る。会話はちょうどその中間に位置する。GitHub Copilot はテンプレートに沿って動くので、最終的に Issue に入るデータは正しく、フォーマットも正しい。そして会話であるおかげで、下流の機械を壊さずに、このイベント固有の細部を調整できる。
始めた頃、この会話はターミナル上の GitHub Copilot CLI で行われていた。自分にとっては問題なかったが、「ターミナルを開く」ことは、この流れに巻き込みたい多くの人にとって壁だった。GitHub Copilot app があれば、同じ会話が普通のデスクトップウィンドウでできる。壁は「shell に慣れていること」から「タイピングができること」まで下がった。
役割分担についてははっきりさせておきたい。これがすべての鍵だからだ。GitHub Copilot が下書きし、私が決裁する。イベント名、メールの件名、日付、その一つひとつに私の署名がなければ先へ進まない。会話が終わると、GitHub Copilot が正しいラベルを付けて GitHub Issue を作成し、そこから先は機械が引き継ぐ。
一つのラベル、一つのイベント、全工程を自動化
event-setup ラベルが issue に付いた瞬間、GitHub Actions workflow が引き継ぎ、以前なら半日がかりだった作業を数分で終える。
- イベントプラットフォーム上で過去のイベントを複製し、新しいランディングページを生成する
- UTM パラメータ付きの URL 一式を生成する。チャネルごとに一本、形式は統一、毎回同じ
- 招待メールを Word ドキュメントとして生成し、リポジトリにコミットする
- メール送信と地域マーケティングのトラッキングを担当するチームに申請 Issue を立てる
- イベントをプロジェクトボードに追加し、フィールドを埋める
- Issue にまとめの返信を投稿し、次に開いた人がすべての情報を一目で把握できるようにする
登録の審査はラベルではなくスケジュールタスクで回す。毎朝、cron で起動する workflow が進行中イベントの最新登録者を取得し、クレンジング済みのリストを共有する。招待制のイベントでは、待機リストをこちらの基準でスクリーニングし(この登録者は enterprise 顧客の開発者か、学生か、それとも我々の役員限定クローズド会に紛れ込みたい競合か?)、通過した場合にのみ承認する。
一番のお気に入りは DRY_RUN というスイッチで、setting(GitHub の用語では repository variable)として保存され、各 workflow が実行前に必ずチェックする。オンにすると、すべての workflow は通常どおり進むが、外部システムには一切触れない。ランディングページも作らず、他のリポジトリに issue も立てず、リストも共有しない。マーケティングチームが自分たちの仕事を自分で自動化しようと思えば、リハーサルの手段が要る。DRY_RUN がそのリハーサルスイッチであり、これのおかげで実験するのが怖くなくなった。
イベント後は slash command 一本
イベントの締め作業は以前が一番面倒だった。参加者をエクスポートし、CRM アップロード用に列を整え、会社名で顧客レコードを突き合わせ、レポートを書く。今はコマンド二本で済む。
/lead-upload は参加者リストを取得し、marketing operations チームが CRM アップロードに必要とする正確な形式に整え、申請 Issue を立て、関連するトラッキング issue を閉じる。/event-report は出席データとアンケート結果を取得し、レポートをコメントとしてイベントの Issue に投稿する。あの、そのイベントのすべての情報を載せた唯一の URL に戻るわけだ。
これは GitHub Copilot agent skills で、一番覚えておいてほしいのは、skill とは Markdown ファイル一枚だということだ。どの skill も SKILL.md である。何を、どの順で、何に気をつけてやるかを文字で書いた手順だ。私が書いたものは、昔頭の中に置いていた runbook をそのまま読むようなものだ。実際そのとおりだから。
runbook が書けるなら、skill も書ける。
skill はこのシステムを柔軟に保つ鍵でもある。アジア太平洋(APAC)地域で、フォローアップの流れがまったく同じ市場は二つとない。オーディエンスが違い、セグメントが違い、ローカルの慣習が違う。ハードコードされた workflow はどの市場も同じ型にはめてしまう。Markdown で書かれた手順は柔軟だ。各市場が、下層の仕組みに手を触れずに、runbook を自分たちの現実に合わせて変えられる。だからイベント後のステップはパイプラインに固定せず、GitHub Copilot skills に置いている。
一つ、skill をコードとして扱っている点がある。新しい skill は pull request で提出し、マージ前にレビューを受け、CODEOWNERS ファイルがレビューを該当のメンテナにルーティングする。承認フロー付きのマーケティング自動化だ。ガバナンスもプラットフォームがただでくれる。
組み込みのガードレールがあるから実験できる
顧客データと API クレデンシャルに触れる workflow を、チーム全員が見られるリポジトリに置いて自動化している。自分で書いたコードはほとんどない。半年前ならこの組み合わせは無謀だと言っただろう。考えが変わったのは、自分が手を動かす前からあまりにも多くのガードレールがすでに整っていたと気づいたからだ。
ガードレールのいくつかは自分で作った。DRY_RUN スイッチ、pull request ごとに走るテストスイート、変更のたびに必要なコードレビュー。どれも開発者の日常的な習慣だ。それがマーケティングの仕事もソフトウェアと同じくらいよく守ってくれるとわかった。
一番重要なガードレールは、プラットフォームが最初から用意してくれているものだ。
- プッシュ保護付きのシークレットスキャン。 私の立場で最も恐ろしいのは、API token をうっかりコミットしてしまうことだ。GitHub のプッシュ保護は、シークレットがリポジトリに入る前にプッシュを止めてくれる。GitHub 自身の token なら、万一すり抜けても自動で失効される。
- GitHub Copilot のデータポリシー。 応募者名簿は業務データで、定型スクリプトは決まったやり方でしか扱わない。だが実際の仕事は決して完全に定型ではない。スクリプトが想定していない一時的なデータの切り口が欲しくなる日もある。GitHub Copilot の商用プランは prompt を保持せず、モデルの学習にも使わないので、こうした場当たり的な分析を直接頼める。業界全体がこっそりやっていること——業務データを隣のタブで開いた適当なコンシューマー向けチャットボットに貼り付ける——をせずに済む。モデルも同じだ。どのモデルを使えるかは組織のポリシーが決めるのであって、私の判断ではない。だから一回限りの実験でも、会社がすでに引いた境界の内側で動く。今回は、安全な道と便利な道が同じ道だった。
スキル化のもう一つの産物は、ほとんど副次的なものだ。各プロセスが名前を持った固定の作業単位になったので、タスクごとにモデルを選べる。組織が承認したモデルの中から選ぶ。速くて安いモデルは日々のリスト整理を担当し、強いモデルはマーケティングコピーを起草する。
もう一つ、実際にあった失敗を共有しておく。同じ轍を踏まないように。朝の選別ワークフローが、誰かがリストの古さに気づくまで五日間も音もなく止まっていたことがある。監視していない自動化は、遅延付きの時限爆弾に近い。定期実行するワークフローには、大きな音で失敗を報せる手段を用意しておこう。そうすれば見逃さない。
一つのタスクから始める
回復途上の手作業者から、もう一人の手作業者への提案だ。
一週間で一番繰り返しの多い作業を一つ選ぶ。そして、それに関わるツールに API や CLI があるか調べてみる。どれだけあるか、おそらく驚く。
次に最小のものを作る。入力を集める issue フォーム、開始を意味するラベル、一つのステップだけを実行する Action。あるいは全部飛ばして、runbook を SKILL.md として書いて GitHub Copilot に実行させる。dry-run スイッチ付きで走らせ、信頼できるようになるまで続ける。そこからゆっくり広げていけばいい。
コードは私が書いたわけではない。すでに知っていること(仕事がどう進むか)を書き出して、あとはプラットフォームに任せただけだ。あなたの「朝の応募者リスト」が何であれ、書き出した runbook が一つあれば、自分自身を片付けてくれるはずだ。
始めるために:
- issue フォームの構文
- GitHub Actions のドキュメント
- GitHub Copilot のドキュメント
- そして、これがうまくいくと私に確信させたブログ記事:私は自分の仕事を自動化した(それが私をより良いリーダーにした)