再現性の根拠・ロジック解説

なぜ同じ最適化構造が誰でも・何回でも再現できるのか

本ページは、Affiliate Post Studio が「集客に効く投稿の型」をどのようにコードへ固定し、 誰が・いつ・何回使っても同じ最適化構造を必ず適用できるのかを、実際の実装に基づいて説明します。 マーケティング的な誇張ではなく、リポジトリ内の functions/generator.js / functions/rules.js / functions/prompt.js / functions/category.js / functions/variation.js / functions/analyze.js / functions/store.js と自動テストに接地した事実のみを記載します。

「型」には序列があります。第一の柱は CTR(クリック率)に効く構造 (X 本文リンク除去でインプレッションを守り、クリック対象をリプライに1本確定させる)が 毎回強制されること。物販リプの正直なデメリット補完は CVR(成約率)に効きます。 一方、ペルソナによる一貫性・似すぎ回避は「凍結回避・実在感」という間接要因として位置づけます。 あわせて Content Quality v2 では、体験を断定しない観察ベースの率直な印象、 履歴照合デデュープ、UTM/subID による成果計測を実装に追加しました。 ただし最後に強調するとおり、成果(集客・成約)の再現性は「計測」によって初めて担保されます。 ツールが再現するのは投稿の「型」であって、収益ではありません。

01このツールは何をするか / 役割分担

ツールは「生成と最適化構造の担保」まで。実投稿の判断は人が行います。

Affiliate Post Studio は、入力した商品・案件情報から X(旧Twitter)の親ポスト・リプライThreads の投稿文、および推奨タグを生成し、 データベースにストック(下書き保存)するための社内ツールです。 生成は functions/generator.jsgeneratePosts()(テンプレート方式)または generatePostsLLM()(LLM方式)で行われ、 どちらの場合も出力は最後に必ず同じ後処理ルールを通ります。

ツールが担うこと(決定論)

  • 投稿文の生成(テンプレート/LLM)
  • 媒体ごとの制約の機械的な担保(文字数・リンク位置・タグ正規化)
  • 誇大・断定表現の除去と誠実な但し書きの補完
  • データベースへのストック・ステータス管理

人が担うこと(最終判断)

  • 生成文の内容確認と必要な手直し
  • 実際に投稿するかどうかの判断と実投稿
  • 画像・動画の用意と添付
  • 公開前の法的リスクチェック

つまりツールは「下書きの最適化構造」までを再現性をもって担保し、 最終的な公開判断は人間が行うという明確な役割分担です。

02「再現性がある」とはどういう意味か

思いつきではなく、コードに固定されたルールが毎回必ず適用される、という意味の再現性。

ここでいう「再現性」は、収益や成果が再現するという意味ではありません。 集客に効く投稿の「型」を、担当者の感覚や思いつきに任せず、 決定論的なルール出力後の強制矯正(enforce)として コードに固定していることを指します。この「型」には序列があり、 CTR(クリック率)/CVR(成約率)に直接効く構造を最上位の柱に据えています。

第一の柱:CTR に効く構造が毎回強制される。 X では本文リンクを除去してインプレッション(表示回数)を守り、 クリック対象のアフィリエイトリンクをリプライに1本だけ確定させます (enforceXParent() で親からリンク除去、enforceXReply() でリプ末尾に1本挿入)。 「表示を最大化し、クリック導線を1点に絞る」というクリック率の起点になる構造が、 生成方式によらず毎回機械的に適用されます。加えて物販リプの正直なデメリット補完 (hasDemerit() / DEFAULT_DEMERIT)は納得を作り、CVR(成約率)側に効きます。

テンプレート生成(generatePosts())は同じ入力に対して常に同じ構造の文面を返します。 LLM 生成(generatePostsLLM())は文言こそ毎回変わりますが、 出力は最後に必ず functions/rules.jsenforce* を通るため、 満たされる制約(型)は常に同一です。

間接要因の柱:凍結回避・実在感。 ペルソナによる文体の一貫性・似すぎ回避(デデュープ)は、CTR/CVR を直接動かす柱ではなく、 アカウントの凍結回避と実在感の担保という間接要因として位置づけます。 これらは投稿を継続的に届けられる状態を守るための土台であり、 クリック・成約に効く構造(第一の柱)とは役割が異なります。

結果として、誰が・いつ・何回使っても、CTR/CVR に効く同じ最適化構造が必ず適用される状態が 担保されます。これがこのツールの「再現性」の中身です。

03観察ベースの率直な印象(体験は断定しない)

実在感は「観察ヘッジの連発」ではなく「具体性」で出す。実使用・体験の断定はテンプレートでも LLM でも一切しません。

1. 「実際に使った/試した/届いた」は書かない

テンプレート(functions/generator.js)も LLM(functions/prompt.js)も、 実使用・体験の断定を一切しません。語りは観察・検討ベース (「調べていて」「口コミを見ていて」「スペックを見た率直な印象として」)に統一し、 そこに推量(「〜できそう」「〜な人に良さそう」)と問いかけを添えます。 これは購入者を誤認させないための景表法配慮であり、コードに固定された方針です。

2. 観察フレーミングは1投稿につき原則1回まで

「調べていて」のような観察ヘッジを毎文に並べると、かえって不自然で逆効果になります。 そこで観察フレーミングは根拠の明示として投稿全体で原則1回までに抑え、 残りは商品名・カテゴリ語・数値といった具体性で実在感を出します。 テンプレートは buildReplyBody() / buildThreadsBody() が観察オープナーを 1回だけ用意し、LLM はシステムプロンプトの観察ルールでこれを指示します。

3. 具体性は捏造ではなく実データで担保

実在感の主役は商品の実データです。functions/analyze.jsfetchProductData() が アフィリエイト先 URL から価格・★評価・レビュー件数・主要スペック・説明を 取得できた範囲だけ(取れなければ付けない=捏造しない)抽出し、 dataLine() が本文に1行として織り込みます。数値が無い場合は数値・スペックを断定せず、 一般的な観察表現にとどめます。応答の productDataUsed で実データ活用の有無が分かります。

04ペルソナによる一貫性

同じ語り手なら、いつ生成しても文体・価値観・口癖が一貫する。

1. 語り手人格をデータとして固定

ペルソナテーブル(tblZ59Vq5ecMEflF)に語り手の 一人称・語尾・トーン・価値観・署名を、フレーズテーブル (tblGUtAeOiw4X5AA)に口癖・言い回しを保存します。 生成時に personaId を指定すると、functions/store.jsgetPersona() / listPhrases() がこれらを読み込み、 functions/prompt.jsformatPersona() / formatPhrases() が システムプロンプトへ注入します(口癖は最大12件から自然に1〜2個を織り込む指示)。

2. ペルソナの NG ワードは追加の禁止語になる

ペルソナに設定した NG ワードは、全社共通の FORBIDDEN_WORDS に加えて そのペルソナ専用の追加禁止語として enforce 段で除去されます。 「このキャラはこの言葉を使わない」という一貫性まで機械的に担保されます。

3. ペルソナ未指定でも安全側に倒れる

personaId を指定しない場合は、温かく誠実な一人称(私)の語り手として 観察ベースで率直に語る既定の人格が使われます。ペルソナの取得に失敗しても生成は止まらず、 ペルソナ無しで続行します(best-effort)。

05反復回避(履歴照合デデュープ)

同じ商材でも投稿が毎回似ないよう、切り口を替え、似すぎたら作り直す。

1. 5種の切り口(angle)から直近未使用を選ぶ

functions/variation.js は5つの切り口(好奇心フック/比較・選び方/悩み共感/ データ・事実起点/ストーリー・観察)を定義します。生成前に store.recentPosts()同じペルソナ・同じカテゴリの直近投稿を取得し、pickAngle()直近で使っていない切り口を優先して選びます。使った切り口は投稿の「切り口」列に保存され、 次回の回避材料になります。

2. 似すぎたら切り口を替えて作り直す(最大3回)

生成文が直近投稿と似すぎていないかを、similarity()(文字 trigram の Jaccard 係数)で測ります。閾値 0.7 以上なら isTooSimilar() が真を返し、 functions/app.js の生成ループが切り口を替えて最大3回まで再生成します。 これにより、量産しても投稿が金太郎飴にならない仕組みです。

06成果計測(UTM/subID)

どのペルソナ・どの切り口の投稿が成果につながったかを、後から計測できるようにする。

1. リンクに計測用 subID を自動付与

投稿を保存するとき、functions/store.jsbuildSubId() / addSubIdToUrl() が、アフィリエイトリンクへ aps=<personaId>_<angle>_<連番> 形式の subID を付与します。 既存のクエリは保持し、ASP 本来の計測軸(楽天の scid / A8 の a8mat)を壊しません。 これにより「どのペルソナ × どの切り口」がクリック・成約に寄与したかを後から切り分けられます。

2. 計測タグは「成果」ではなく「検証可能性」を生む

重要な点として、subID を付けただけで成果が出るわけではありません。 計測は結果を観測し、効いた切り口・ペルソナを次に活かす PDCA を回すための土台です。 次章以降の媒体ロジックが担保するのは投稿の「型」であり、 その型が実際に集客・成約へつながるかどうかは、この計測データで初めて確かめられます

07X(旧Twitter)のロジックと根拠

X 親ポスト + リプライ

1. 親ポスト(140字以内・リンク無し)+ リプライ(リンク)に分割

親ポストはリンクを含めず本文だけで「続きが読みたくなる引き」を作り、 アフィリエイトリンクはリプライ側に置きます。 これは、本文にリンクを含めるとリンクペナルティでインプレッション(表示回数)が落ちやすいことを 回避するための分割です。コードでは enforceXParent() が親ポストから リンク・裸の http/https リテラルを除去し、 X_PARENT_MAX = 140 を超える場合はコードポイント単位で安全に短縮します。 リンクは enforceXReply() がリプライ末尾に必ず挿入します。

2. ハッシュタグ非使用

ハッシュタグはリーチ拡大に寄与しないと判断し、X 側では一切使いません。 validateXParent() / validateXReply()# の混入を違反として検出し、 enforceXParent() / enforceXReply()stripHashtags() で機械的に除去します。

3. 正直なデメリットの記載

物販(rakuten / a8)のリプライには、良い点だけでなく正直なデメリット・懸念点を最低1つ必ず含めます。 納得して購入してもらうことで信頼とCVR(成約率)を高める狙いです。 hasDemerit()DEMERIT_HINTS(「ただ」「注意」「人を選ぶ」等)の有無を確認し、 無ければ enforceXReply()DEFAULT_DEMERIT (「ただ、合う合わないは人を選ぶので、その点だけは注意してください。」)を補完します。 リプライ冒頭には disclosure() による広告明示 (楽天なら「※広告 楽天アフィリエイトを含みます」)が入ります。

08Threads のロジックと根拠

Threads 単独投稿

1. ハッシュタグは1つだけ(末尾の単一タグ語)

Threads は本文中に # 記号を使わず、最終行に単一のタグ語のみを置く形に統一します。 enforceThreads() は本文から # を除去(stripHashtags())したうえで、 normalizeTag() で正規化したタグ語を末尾に1つだけ付与します。 normalizeTag() は記号・空白・禁止語を取り除き、空になった場合は フォールバック("おすすめ")を返すため、タグが必ず1語で確定します。 validateThreads() は「# が含まれていないこと」と 「最終行が空白を含まない単一タグであること」を検証します。

2. 画像・動画の添付枠

Threads は画像・動画が表示面で有利なため、本文に添付プレースホルダを必ず確保します。 hasImagePlaceholder() が枠の有無を確認し、無ければ enforceThreads()DEFAULT_IMAGE_PLACEHOLDER(「[ここに商品の魅力的な使用画像を添付]」)を補完します。 実際の画像は人が用意して差し替えます。

3. 柔らかく対話的なトーン

フォロワーとの対話を促すため、本文には問いかけ(?)を含めます。 テンプレートは「みなさんは普段こういうとき、どうしていますか?」のような問いかけを最初から含み、 LLM 出力で問いかけが欠落していた場合は enforceLlmResult() が 問いかけ文を補完してから enforceThreads() に渡します。

09オプトイン(無料オファー)のロジックと根拠

optin ネットワーク

1. 無料オファー訴求・登録ハードルの低減を前面に

オプトインは「無料で受け取れる」「登録するだけ」という低ハードルを前面に出します。 CTA(行動喚起)の語彙は「無料で受け取る/登録する/チェックする」に限定し、 「購入」のような購買誘導語は使いません。広告明示は disclosure() により 「※PR 無料オファーのご案内です」となります。

2. 誠実な但し書きで誇大・断定を避ける(景表法配慮)

無料を強調する一方で、「登録は無料だが案内メールが届く」等の正直な但し書きを必須にしています。 hasOptinDisclaimer() は本文に「無料」と OPTIN_HONEST_HINTS (「メール」「案内」「ご了承」等)の両方が含まれるかを確認し、無ければ enforceXReply()DEFAULT_OPTIN_DISCLAIMER (「登録は無料ですが、後日ご案内のメールが届く点だけご了承ください。」)を補完します。

さらに FORBIDDEN_WORDS(「絶対」「必ず」「100%」「誰でも」「確実」「稼げる」等)は stripForbiddenWords() によって全媒体・全ネットワークで除去されるため、 誇大・断定・射幸的な表現が出力に残らない設計です。

10技術的な裏付け(コードに接地)

functions/rules.js の enforce 関数群が、生成方式によらず同じ制約を機械的に保証します。

テンプレート生成でも LLM 生成でも、最後は必ず同じ enforce* を通ります。 LLM 出力の場合は functions/generator.jsenforceLlmResult() が各フィールドを 下記の enforce* に渡すため、LLM が制約を破っても出力は矯正されます。

enforceXParent(text)
ハッシュタグ除去 → リンクと裸の http/https 除去 → 禁止語除去 → 140字超過時はコードポイント単位で安全短縮(末尾「…」)。
enforceXReply(text, url, network)
ハッシュタグ・禁止語除去 → 物販はデメリット、optin は但し書きを補完 → アフィリエイトリンクが無ければ末尾に必ず挿入。
enforceThreads(text, tag)
normalizeTag() でタグ正規化 → 禁止語・# 除去 → 画像枠補完 → 最終行を単一タグ語に確定。
normalizeTag(tag, fallback)
#・空白・禁止語を除去し1語に正規化。空になればフォールバック(既定 "おすすめ")を返す。
stripForbiddenWords(text)
FORBIDDEN_WORDS を長い語から順に除去し、誇大・断定・射幸表現の取りこぼしを防ぐ。
cpLength(text)
全角・半角を問わずコードポイント単位で文字数を数える。140字判定の基準。

enforce* には対になる validateXParent() / validateXReply() / validateThreads() があり、 違反を文字列のリスト(空配列=合格)で返します。これにより「矯正後の出力が本当に制約を満たすか」を 機械的に確認できます。

自動テストによる継続検証

210
test/generate.test.mjs
rakuten / a8 / optin・空入力・超長文・タグ混入など 13 ケースで全制約を検証(PASSED 210 / FAILED 0)。
49
test/enforce.llm.test.mjs
わざと制約違反だらけのダミー LLM 出力を enforceLlmResult() に通し、全制約への矯正を検証(PASSED 49 / FAILED 0)。
192
test/generator_v2.test.mjs
v2 のテンプレ経路。観察表現・体験非断定・切り口(angle)差・商品データの織り込みを検証(PASSED 192 / FAILED 0)。
33
test/rules_v2.test.mjs
カテゴリ別ガード。耐久財への消耗品語彙混入の除去など、カテゴリ不整合の正規化と後方互換を検証(PASSED 33 / FAILED 0)。
$ node test/generate.test.mjs
PASSED: 210 / FAILED: 0
ALL CONSTRAINTS SATISFIED

$ node test/enforce.llm.test.mjs
PASSED: 49 / FAILED: 0
LLM 矯正: 全制約を満たしました

$ node test/generator_v2.test.mjs
PASSED: 192 / FAILED: 0
GENERATOR v2: テンプレート経路の全制約・観察表現・angle差・productData織り込みを満たしました

$ node test/rules_v2.test.mjs
PASSED: 33 / FAILED: 0
CONTENT QUALITY v2: 全制約を満たしました

$ node test/rules.regression.test.mjs
PASSED: 31 / FAILED: 0
REGRESSION: 全負例の固定に成功しました

これらのテストは依存ゼロの純 Node 実行で、140字・リンク位置・# 除去・タグ正規化・デメリット/但し書き・広告明示・問いかけ・画像枠に加え、 v2 の観察表現・体験非断定・カテゴリ整合・切り口差・商品データ織り込みを継続的に検証します。 テストが通る限り、生成方式が変わっても担保される「型」は同一です。

11誠実性と免責

再現できるのは「最適化構造」であり、成果ではありません。

本ツールが再現するのは「投稿文の生成と最適化構造の担保」であり、収益・成果を保証するものではありません。

成果(集客・成約)の再現性は、計測によって初めて担保されます。 ツールは「型」を毎回同じく適用できますが、その型が実際に効くかは市場・商材・タイミングに依存します。 v2 の UTM/subID 計測は、どのペルソナ・切り口が成果につながったかを観測可能にするための土台であり、 計測データに基づく PDCA を回して初めて「再現できる成果」に近づきます。 計測なしに成果が再現するという主張はしません。

投稿の最終的な内容確認と、実際に投稿するかどうかの判断は人間が行います。 生成文はあくまで下書きであり、そのまま公開することを前提としていません。

アフィリエイト・PR である旨は disclosure() により必ず明示されます (「※広告」「※PR」)。広告であることを隠す運用は行いません。

公開する文面は、景品表示法・特定商取引法・個人情報保護法・保険業法等の観点から、 公開前の法的リスクチェックを経たうえで公開してください。 禁止語の機械的除去や但し書き補完は配慮の一部であり、最終的な適法性判断を代替するものではありません。

本ページは社内向け技術ドキュメントです(noindex)。記載内容は functions/generator.js / functions/rules.js / functions/prompt.js / functions/category.js / functions/variation.js / functions/analyze.js / functions/store.js / functions/app.js および functions/test/generate.test.mjs / enforce.llm.test.mjs / generator_v2.test.mjs / rules_v2.test.mjs / rules.regression.test.mjs の実装に基づきます。実装の変更時は本ページも更新してください。