メインコンテンツへスキップ
受託受付中相談する
設計思想

LPの公開を2段階ゲートで守る — winner + noindex

LP PoCを量産する運用では、「検証中のLPが誤って検索結果に出る」事故 が一番怖い。 未完成の訴求が露出するとブランドが薄れ、計測ノイズも増える。 LeapLensでは、frontmatterの単一フラグではなく2つの条件のANDで公開判定している。

単一フラグだと事故が起きる

最初は noindex: true をfrontmatterのデフォルトにし、公開時に false に書き換える方式を考えた。 だが1行のミスで露出してしまうのが怖い。コードレビューで気づけば良いが、PoCを高速で回す現場で常に通るとは限らない。

statusとnoindexの二段階

そこで状態管理用の status を別軸で導入した:

type LpStatus = "draft" | "running" | "winner" | "archived";

そして公開判定:

export const isPubliclyDiscoverable = (data) =>
  data.status === "winner" && data.noindex === false;
  • draft: 書き始め
  • running: 検証中(常にnoindex)
  • winner: 採用決定。ここで初めて noindex: false を意図的に書く
  • archived: 終わった検証(再びnoindex)

status がwinner以外なら、たとえfrontmatterに noindex: false と書いても 強制的にnoindexが出る。 逆に status: winner でも noindex のデフォルトtrueのままなら公開されない。 二段階の意図 が必要なので、片方の事故では出ない。

三重防壁

それでも漏れることはある。だから多層化する:

レイヤ 仕掛け
Page meta <meta name="robots" content="noindex,nofollow">
robots.txt Disallow: /lps/
Vercel header X-Robots-Tag: noindex, nofollow (vercel.json)

この3つはすべて同時に効くので、どれかが抜けても残りで守れる。

公開フロー

実際の手順:

  1. pnpm new:lp <slug> で雛形を作成。status: draft と noindex: true が入る
  2. status: running に変更して検証開始(noindexはそのまま)
  3. 採用決定したら status: winner + noindex: false を 両方 書き換え
  4. それで初めてインデックス対象になる

なぜ「採用済」だけが公開対象か

採用されたLPは、もはやPoCではなく 本番の訴求 として独立した価値を持つ。 それは独立URLでインデックスされる意味がある。 逆に「検証中」「終了」は、本来仮置きや学習素材なので、検索結果にあるべきではない。

まとめ

  • 1つのフラグでは事故が起きやすい
  • status と noindex の2つの軸をANDで要求すると、意図的な行動が必須になる
  • さらに3重のnoindex (meta / robots / header) で漏れを防ぐ
  • 状態が言語化されているので、レビューも自然になる

LPの量産はスピードと品質のトレードオフだが、この公開ゲートのおかげで、安心してドラフトをrepoに置けるようになった。