アプリランディングページSEO
アプリのストア掲載情報を、高コンバージョンかつSEO最適化されたランディングサイトとロングテールガイドページに変換するためのエンドツーエンドワークフローです。デフォルトのスタックは Vite + React + ビルド時プリレンダリング(フェーズ3で説明)。リポジトリにすでにWebフレームワーク(Next.js、Astro)がある場合は、その中で構築し、出力パスを適宜変更します。各フェーズは検証で終わります。
このスキルは、同じリポジトリに含まれる別途インストールされた gpt-image スキルに依存します。ガイド画像が必要な場合は、そのスキルを読み込み、その指示に従ってください。そのヘルパーがこのスキルのディレクトリ内にあるとは想定しないでください。
フェーズ1 — ストア掲載情報を取得(信頼できる唯一の情報源)
-
iTunesルックアップAPIから完全なメタデータを取得します(認証は不要):
curl -s "https://itunes.apple.com/lookup?id=<APP_ID>&country=us"抽出する項目:name、bundleId、description、price/IAP terms、genres、rating count、screenshots、icon、version、seller。Google Playの掲載情報も確認します(
play.google.com/store/apps/details?id=<bundleId>)— iOSのみと想定しないでください。 -
mzstaticのサムネイルサフィックスを書き換えて、高解像度でアセットをダウンロードします:
- アイコン:
512x512bb.jpgを1024x1024bb.pngに置き換え - スクリーンショット:
392x696bb.jpgを1284x2282bb.pngに置き換え(グレースフルにフォールバック;fileコマンドで検証)
- アイコン:
-
Readツールで全てのスクリーンショットを読み取ります。 キャプション、ガイドトピック、ランディングコピーは、スクリーンショットが実際に示している内容を説明する必要があります。また、スクリーンショットからブランドパレットとタイプスタイルを抽出します。
-
リポジトリルートに
app.mdを書き込みます:識別テーブル、逐語的な説明、リスティングとスクリーンショットから導出した機能リスト、アセットマニフェスト、その後キーワードリサーチ(フェーズ2)とプレースメントマップを記載。このファイルは以降のすべての契約書となります。
フェーズ2 — コンバージョンに結びつくキーワードリサーチ
astroMCPツールが接続されている場合、get_keyword_suggestionsとsearch_app_storeを使用して、App Storeでの人気度/難易度と現在の順位を取得します。今日のアプリのランキングを記録します。- WebSearchを使用して、Google側のロングテールキーワードを検証します(ランディングページはGoogleでランクインし、App Storeではありません)。
- 出力を
app.mdに構造化します:- プライマリキーワード(3〜5のヘッドターム) → タイトルタグ、H1、ヒーローコピー、メタディスクリプション
- セカンダリ → セクションH2、機能コピー
- ロングテール(6〜10の質問/タスクフレーズ) → それぞれ1つのガイドページ
- 重要なルール:
- すべてのロングテールは、アプリが実際に解決する痛点にマッピングする必要があります — 理想的にはスクリーンショットに表示されているもの。それがトラフィックをコンバージョンに結びつけるものです。
- 各ヘッドタームの実際のSERPを確認し、ポイズンされたもの(例:「在庫管理ソフトウェア」がエンタープライズベンダーを返す場合)はスキップします。
- ブログがランクインしているHowToフレージングを優先します — HowTo/FAQスキーマを持つアプリページはブログに勝つことができます。
フェーズ3 — ランディングページのオンページSEO
Vite + React SSGアーキテクチャ(デフォルト)
SPAはJSレンダリングなしではクローラーに見えません。そのため、プリレンダリングされた静的HTMLを提供します。SSGフレームワークは不要です — 約30行のプリレンダースクリプトで済み、通常ページは ゼロのクライアントJS で動作します(FAQアコーディオンはネイティブの <details> タグを使用;インタラクティブ性がないものはハイドレートしないでください):
landing/
package.json # build: vite build --ssr src/entry-server.tsx --outDir dist-ssr && node scripts/prerender.mjs
vite.config.ts # plugins: [react()], ssr: { noExternal: true } ← reactをdist-ssrにバンドルし、prerender.mjsが単独でインポートできるようにする
index.html # 開発時のみのシェル:<div id="root"> + /src/entry-client.tsx
public/ # style.css、assets/(そのままdist/にコピー)
src/
data.ts # 全てのコンテンツ:FAQエントリ、ガイド本文、タイトル、説明文。唯一の情報源。
seo.ts # PageMeta型 + JSON-LDビルダー(homeJsonld、guideJsonld、breadcrumbJsonld)でdata.tsから読み込む
components.tsx # Header、Footer、StoreBadge、FaqItem、GuideCard、CtaCallout
pages/ # Home.tsx、GuidePage.tsx、GuidesIndex.tsx
routes.tsx # ROUTES:[{ meta: PageMeta, element }] — ページごとに1エントリ、ガイドはdata.tsから展開
entry-server.tsx # renderRoute(route):完全なHTMLドキュメント文字列 — headタグ + JSON-LD + renderToStaticMarkup(body)
entry-client.tsx # 開発時のみ:matchRoute(location.pathname) → createRoot().render()
scripts/prerender.mjs # dist-ssr/entry-server.jsをインポート;ルートごとにdist/<path>/index.html + sitemap.xml + robots.txtを書き出し;cpSync public/ → dist/
この形状に組み込まれた重要な決定事項:
renderToStaticMarkup、renderToStringではない — ハイドレーションマーカーなし、クリーンなHTML、クライアントバンドルは出荷されないため。- クリーンURL:ルートパスは
/で終わり(/guides/<slug>/)、プリレンダーは<path>/index.htmlを書き出します。内部リンクはサイト絶対パス(/guides/…/)で、これにより開発サーバーのナビゲーションも機能します。 - 開発体験:
viteはHMR付きでentry-client.tsxを提供;クライアントエントリは本番環境に出荷されません。 - 手動で構築したheadテンプレートで
esc()属性値をエスケープ;JSON-LDはJSON.stringifyを使用(エスケープの問題なし)。 - React属性は
fetchPriority(キャメルケース)— 小文字のfetchpriorityは警告を出します。
オンページルール(任意のスタック)
セクション:ヒーロー、ダウンロード、スクリーンショット、仕組み、ガイド、FAQ、CTA、フッター。
- H1はちょうど1つで、プライマリキーワードを含むこと。セクション見出しはH2(「利用可能な環境」スタイルの見出しはH1にしないでください)。
<title>≈ 「ブランド — プライマリキーワード(対象者向け)」(60文字以下)。メタディスクリプションは155文字以下で、プライマリキーワードとトップの差別化要因を含むこと。- ページごとに正規URL、OG + Twitterカード、
apple-itunes-appメタ(スマートアプリバナー)。Vite設定ではこれらはentry-server.tsxに;Next.js:metadataBase、alternates.canonical、titletemplate、itunes.appId。 - ホームページのJSON-LD:
SoftwareApplication(offers、installUrlを含む;評価が約50未満の場合はaggregateRatingを省略)、FAQPage、WebSite。seo.tsでオブジェクトをdata.tsから構築し、スキーマと表示コピーが1つのソースを共有するようにします。 - ストアバッジ/ダウンロードCTAをファーストビューに、さらに下の方に繰り返しのCTAセクションを配置。
- スクリーンショットには、実際の画面を説明するキーワードを含む
altテキストを付けます。ストアのPNG(多くの場合1〜2 MB)を200 KB以下のJPEGに再圧縮します(sips -Z 1386 -s format jpeg -s formatOptions 80);オリジナルはpublic/assets/full/に保持。 - FAQ:8〜10の質問で、それぞれが実際の検索クエリであること。2〜3文で回答し、それぞれに該当ガイドへの「もっと詳しく →」リンクを付けます。FAQPage JSON-LDは、表示されるFAQと同じQ/Aテキストを含む必要があります — 両方とも同じ
data.ts配列からレンダリングされます。 sitemap.xml+robots.txt:scripts/prerender.mjsがROUTESリストから生成するため、新しいガイドが自動的に追加されます。
フェーズ4 — ガイドページ(ロングテールキーワードごとに1つ)
ガイドコンテンツは1つのデータモジュール(Vite設定の src/data.ts;Next.jsの lib/guides.ts)に保存し、単一のテンプレートコンポーネントでレンダリングすることで、スキーマ、カード、フッターリンク、サイトマップがすべて同じリストから派生するようにします。各ガイドを構造化データとしてモデル化し、HTMLブロブにしないでください:{ slug, title, description, h1, intro, featureImage: { src, alt, width, height }, howto?, sections: [{ h2, paras, cta?, figure? }], faq, related } — CTA呼び出しと図はコンポーネントになり、段落は検索可能な文字列のままにします(インラインの <em> レベルのHTMLは dangerouslySetInnerHTML で問題ありません)。
GPT画像機能画像ワークフロー
すべてのガイド記事は、それぞれ独自の横向きの機能画像を取得します。gpt-image スキルを読み込んで使用します。このスキルはOpenAIの gpt-image-2 を呼び出します。ユーザーが明示的に要求しない限り、ストック画像、CSSグラデーション、スクリーンショット、または別の画像モデルに置き換えないでください。gpt-image がインストールされていない場合は、画像生成を中止し、ユーザーにこのリポジトリから兄弟スキルをインストールするように伝えてください。
- ガイドのタイトルとスラッグが確定したら、その検索意図、具体的な主題、および
app.mdでキャプチャされたアプリのビジュアルアイデンティティから、ガイドごとに1つの画像ブリーフを作成します。コンセプトは意味的に異なるものでなければならず、1つの構図のパレットスワップであってはなりません。 - アプリのブランドパレットで、編集用機能画像用のプロンプトを作成します。被写体、設定、構図、照明、素材、カメラ/視点、および視覚的な余白がどこにあるべきかを説明します。すべてのプロンプトを次で終わらせてください:
横向きの編集用機能画像、3:2の構図。テキスト、単語、文字、数字、キャプション、透かし、インターフェースラベル、ロゴは絶対に含めないでください。モデルに記事タイトルをレンダリングするよう求めないでください。 GPT_IMAGE_SKILL_DIRを、gpt-imageスキルのSKILL.mdを含むインストール済みディレクトリに解決し、決定論的な出力先でそのジェネレーターを実行します:これにより、1536×1024の横向きソースが生成されます。必要に応じて最初に出力先ディレクトリを作成します。生成されたソースを保持します。フレームワークの画像パイプラインを使用して、より小さなレスポンシブバリアントを作成し、繰り返し再圧縮しないようにします。"$GPT_IMAGE_SKILL_DIR/scripts/generate_image.py" "<guide-specific prompt>" \ --model gpt-image-2 \ --aspect-ratio 3:2 \ --quality high \ --background opaque \ --format webp \ --output "<site-public-dir>/assets/guides/<slug>-feature.webp"- 画像を配線する前に、すべての画像をフルサイズで検査します。誤ったテキスト/グリフ、不正な形状のオブジェクト、コピーされたアプリUI、意図しないロゴ、無関係な被写体、デスクトップおよびカードのアスペクト比でのトリミングの安全性の低さを確認します。失敗した画像のみを再生成し、観察された欠陥に対処するためにプロンプトを変更します。同じガイドで2回失敗したら停止し、残りの問題を報告して、無期限に費やさないようにします。
- 画像をガイドの構造化レコードに追加します。
width: 1536、height: 1024、および画像が実際に何を含むかに基づいた簡潔で説明的なaltテキストを付けます。記事のファーストビューの機能画像、ガイドカードのサムネイル、ページのog:image/twitter:imageとしてレンダリングします。Article.imageJSON-LDに絶対URLとして追加します。altテキストがピクセルを説明していない場合、検索キーワードを定型altテキストとして使用しないでください。
ガイドごとに:
- URLスラッグ = キーワード(
/guides/how-to-keep-track-of-inventory-small-business) - 回答ファーストの冒頭:最初の段落が検索された質問に直接回答します(注目スニペットの餌)。その後、本文はアプリをツールとして織り交ぜながらタスクを教えます — 先に教え、後で売り込みます。
- H2はキーワードの二次的なフレージングを運びます。600〜900語の実質的な内容で、無駄なものはありません。
- 説明的なキャプション付きの関連アプリスクリーンショット、ページ中央のCTA呼び出し、そのガイドに固有の2つの質問のFAQ(ホームページのFAQの質問と重複しないでください — スキーマの重複)。
- JSON-LD:
Article+BreadcrumbList+FAQPage、ガイドがステップ形式の場合はHowToも追加。 - ガイド同士を相互リンクし、ホームページのセクションに戻るリンクも配置します。
- 生成されたGPT画像機能アセットが存在し、記事に固有であり、ヒーロー、カード、ソーシャルメタデータ、および
Article.imageJSON-LDに配線されています。レスポンシブなsrcset/フレームワークの画像最適化を使用し、明示的な寸法を設定してレイアウトシフトを防止します。ファーストビューの機能画像を遅延ロードしないでください。
フェーズ5 — コピーのスロップ除去(Wikipedia:AI作成の兆候)
出荷前に、作成したすべてのコンテンツ(ガイド、FAQの回答、ヒーロー/セクションコピー)に対してこのパスを実行します。兆候は、目立つ順に:
- Emダッシュ — 最大の兆候。予算:サイト全体で一握り、段落ごとではない。ピリオド、カンマ、コロン、括弧に置き換えてください。
- 否定の並列 — 「Xではなく、Yです」、「XだけでなくY」、「X、Yではない」。サイト全体で最大1つ、そしてそれが価値がある場合のみ。
- 3のルール — 「AもBもCもない」、「形容詞、形容詞、形容詞」。ペアか実際のリストに分割してください。
- 定型的な構造 — ページ間で同一のオープニング(例:すべてのガイドが同じ太字のテーゼテンプレートで始まる)。変化させる:直接回答、シナリオ、平易な主張。
- 均一なパンチの効いたリズム — 短い文が次々と決めゼリフを放つ。文の長さを変化させる;単に情報を伝えるだけの文も許容する。
- 禁止語彙リスト:delve、tapestry、testament、pivotal、crucial、vibrant、seamless、effortless、boasts、leverage、elevate、robust、meticulous、landscape、underscore、showcase、foster、transformative、game-changing、revolutionize、empower、streamline、「キラー機能」、「単一の情報源」、「自信を持って」、「要するに/ここにその方法があります」の繰り返し。
- 繋辞の回避 — 「is」で十分なのに「serves as」、「stands as」、「represents」を使用。「is」を使用してください。
- 表面的な分析の分詞 — 「…highlighting」、「…underscoring」、「…reflecting」節が文末に付け足されている。
- 格言を具体的なもの(価格、月、名前のあるオブジェクト)に置き換えてください。具体的なものは人間的に読まれ、一般論は生成的に読まれます。
機械的なチェック(パスを適宜変更):
grep -o "—" <content files> | wc -l # 目標:サイト全体で1桁
grep -inE "delve|tapestry|testament|pivotal|crucial|vibrant|seamless|effortless|boasts|leverage|elevate|robust|meticulous|landscape|underscore|showcas|foster|transformativ|game.chang|revolutioniz|empower|streamlin|serves as|stands as|it's not just|isn't just|not only" <content files>
CSSクラス名(例:transition-transform)は誤検出されます。それらは無視してください。残すものは、「忙しい人間がこの文を書くだろうか?」という質問に耐えられるものでなければなりません。
スロップ除去中に維持するもの:スラッグ、見出し/キーワード、内部リンク、スキーマ(書き換えられたソースからスキーマを再生成し、表示テキストとJSON-LDが同一のままであることを確認)。
フェーズ6 — 検証
npm run buildが成功する必要があります。その後、dist/**/index.htmlに対してスクリプト化されたチェックを実行します:ページごとにH1がちょうど1つ、正規URLが存在する、すべての<script type="application/ld+json">がパース可能、すべての内部href/srcがdist内のファイルに解決される(末尾スラッシュのURLを<path>/index.htmlにマッピング)、すべてのsitemap<loc>が実際のファイルにマッピングされる、ホームページの表示されるFAQの質問がFAQPage JSON-LDのnameと等しい。- すべてのガイドレコードが固有の横向き機能画像を持ち、すべてのファイルがビルド出力に存在し、内在的な寸法が幅>高さであり、HTMLのwidth/height属性がソースと一致し、各ガイドのOpen Graph、Twitter、および
Article.imageURLが...