mcpField
E
email-generation

email-generation

github.com/extruct-aiマーケティング・グロース11149 回インストール4 週間前に更新
リポジトリ

email-generation について

email-generationは、固定のメールシーケンスと入力済みの連絡先CSVを、レビュー用および配信用形式に変換するレンダラーです。バリアント選択やフィールド置換、出力検証を行い、LLMによる文面生成は行いません。

主な機能

  1. 01行のキーに基づくメールバリアント選択
  2. 02宣言済みのフォールバックを伴うフィールド置換
  3. 03レビュー用・HTML・プレーンテキスト本文の生成
  4. 04プレースホルダーと出力品質の検証
  5. 05メールCSVと人が読めるレビュー文書の出力
  6. 06キャンペーンの抑制リストへの準拠

活用シーン

  1. 01連絡先ごとのキャンペーンシーケンスのレンダリング
  2. 02HTMLおよびレビュー用メール出力の作成
  3. 03テンプレートや入力データの修正後の再レンダリング
  4. 04出力前の抑制対象連絡先の除外

インストール

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

$npx skills add https://github.com/extruct-ai/gtm-skills --skill email-generation

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

同梱ファイルreferences/render_emails.py

詳細

メール生成(レンダラー)

固定のテンプレートセット(email-prompt-building の sequence.md)と、{{input_fields}} がすでに入力済みの連絡先 CSV から、一連のメールをレンダリングします。このスキルは機械的な処理を行います。バリアントを振り分け、プレースホルダーを置換し、出力形式にレンダリングして、出力 CSV を書き出します。

**ここでは LLM を呼び出しません。**戦略的な推論はすべて設計時(email-prompt-building)に行われ、行ごとの処理に必要な情報はすべて、上流の正規化とエンリッチメントによって入力フィールドに設定されています。メールに誤りがある場合は、テンプレートか入力データに問題があります。ソースを修正して、再レンダリングしてください。

アーキテクチャの原則

このスキルはレンダラーであり、推論するものでも実行を制御するものでもありません。

template set (sequence.md) ─┐
                            ├──▶ route variant ─▶ substitute ─▶ render to target ──▶ emails CSV
contact CSV (fields filled) ┘

必要な入力

入力ソース必須
テンプレートセットemail-prompt-building のキャンペーン用シーケンスファイルはい
連絡先 CSV正規化とエンリッチメントによって入力フィールドがすでに設定済みはい

連絡先 CSV には、ルーティングキーとともに、テンプレートの「Input Fields」コントラクトに記載されたすべてのフィールドを含める必要があります。行に宣言済みフィールドがない場合は、そのフィールドに定義されたフォールバックを適用してください。データを補えない行は削除し、その旨を報告してください。

レンダリングコントラクト

このパイプラインで実際に問題が発生するのは、レンダリングの段階です。「プレースホルダーを置換する」という説明では、改行とエスケープという難所が曖昧なままです。このコントラクトは必須です。

改行モデル

テンプレートでは 2 種類の改行を使い分けているため、レンダラーはその違いを必ず保持する必要があります。

  • \n\n(空行) = 段落区切り
  • \n(単独) = 段落内のソフト改行(意図的に使用)
レンダリング先 — 本文は 1 つ、出力は 3 種類
対象改行の処理エスケープ
review(emails.md / CSV の body 列)\n\n と \n をそのまま保持なし。ただし、CSV ライターは複数行のセルを必ず引用符で囲む
html(Instantly / シーケンサー)\n → <br />(したがって、\n\n → <br /><br />)コンテンツ内の & < > を HTML エスケープ
plain(プレーンテキストのチャネル)そのまま保持なし
処理順 — 必ず守ること
  1. バリアントを振り分ける — ルーティングキー(例:customer_segment)を使って、タッチのバリアントを選択します。
  2. {{fields}} をプレーンテキストの本文に置換する。
  3. 完成した文字列に対し、最後にエスケープと改行変換を行う。

この順序が必要な理由:置換前にテンプレートを HTML エスケープすると、Johnson & Johnson のようなフィールド値がエスケープされずに入り、HTML が壊れます。完成した文字列をエスケープすれば、テンプレート本文と置換後の値の両方を対象にできます。

レンダラーの実装例
import html

def render(body: str, target: str) -> str:
    """body: assembled plain-text (variant chosen, {{fields}} substituted).
    target: 'review' | 'html' | 'plain'."""
    if target in ("review", "plain"):
        return body
    if target == "html":
        # escape content per line, THEN join with <br /> — never escape the tags
        return "<br />".join(html.escape(line) for line in body.split("\n"))
    raise ValueError(target)
レンダラーが防ぐべき失敗
  • バグ第 1 位 — \n → <br> の変換忘れ:メールが文字の塊として届きます。HTML シーケンサーでは必ず変換してください。
  • 置換前のエスケープ — & < > を含むフィールド値で HTML が壊れます。
  • 二重エスケープ — &amp;amp; になります。最後の手順で、1 回だけエスケープしてください。
  • 複数行の CSV セルを引用符で囲まない — body 列内の改行によって、行や列がずれます。適切な CSV ライターを使用してください。
  • 未置換のプレースホルダー — 書き出す前に、出力内に {{ が一つも残っていないことを必ず検証してください。{{company_name}} が残っている場合、そのフィールドが渡されていません(例:Touch 3 に company_name が渡されていない)。

ワークフロー

ステップ 1:入力を検証する
  • テンプレートセットを読み込み、すべての {{field}} とルーティングキーを収集します。
  • 連絡先 CSV のヘッダーを読み込み、宣言済みのすべての入力フィールドとルーティングキーが含まれていることを確認します。
  • 不一致があれば報告し、レンダリングを始める前に停止します。
ステップ 2:行ごとにレンダリングする

各連絡先について、各タッチで次の処理を行います。

  1. タッチにバリアントがある場合は、バリアントを振り分けます。
  2. 入力フィールドをプレーンテキストの本文に置換し、値が空の場合はフィールドごとのフォールバックを適用します。
  3. 必要な各対象(review、html)にレンダリングします。
  4. {{ が残っていないことを検証します。

件名:最初のタッチにのみ設定します。フォローアップではスレッドを継続するため、件名は空にします。

ステップ 3:出力を書き出す
  • メールの CSV — (連絡先 × タッチ)ごとに 1 行:email, first_name, company_name, touch, variant, subject, body, body_html, gaps。gaps 列には、フォールバックしたフィールドを記録します(例:industry=fallback)。
  • 人が読みやすいレビュー用ファイル — セクションごとにメールを 1 通記載します。

両方とも、GTM プロジェクトのキャンペーンアセットの保存先に書き出します。参照用レンダラーについては、references/render_emails.py を参照してください。

ステップ 4:品質チェック
  • すべての行で未置換の {{ が 0 個
  • バリアントの振り分けが正しい — 各バリアントにつき 1 行をスポットチェック
  • \n\n と \n がどちらも HTML 出力に <br /><br />/<br /> として保持されている
  • &/< を含むフィールド値がエスケープされて出力される(生のままでも二重エスケープでもない)
  • 行数 = 連絡先 × タッチ数。フォールバックが適用された箇所では gaps が入力されている
  • フォローアップのタッチでは件名が空

フィードバックループ

ユーザーからメールの問題が指摘された場合:

  1. コピーの問題(→ email-prompt-building を使ってテンプレートを修正)か、データの問題(→ 入力フィールドが正しくなるように正規化/エンリッチメントを修正)かを特定します。
  2. 再レンダリングします。個別のメールを手作業で編集してはいけません。修正箇所は必ずテンプレートか入力データです。

抑制リスト

出力 CSV を書き出す前に、GTM プロジェクトの抑制リストにメールアドレスが登録されている連絡先を除外します(配信停止、バウンス、使用停止アドレス)。このリストの保存場所はプロジェクト側で管理します。このスキルはリストに従うだけです。

まだテンプレートがありませんか?

キャンペーン用の sequence.md がない場合は、email-prompt-building スキルを使って設計します。このスキルでコピーを即興で作成してはいけません。このスキルはレンダリングのみを行います。

コメント