Astro Marketing Site Launch Checklist
静的マーケ/ブログ/LPサイト(Astro 前提、他SSGにも概ね応用可)を最初から品質高く作るためのチェックリスト。過去プロジェクトで「最初から良かった土台」と「後追いで直した改善」を、視点別に整理したもの。
新規着手時・公開前監査時に、下の視点マップから該当セクションを確認する。
視点マップ(どの観点か一目でわかる)
| 視点 | 目的 | セクション |
|---|---|---|
| 土台 | 最初から満たすべき最低ライン | ✅ 既に良かった土台 |
| 守り | 検索・AI・クローラに正しく届ける | 1 SEO / 2 AIO・フィード |
| 回遊 | サイト内を回してもらう | 3 回遊性 |
| 体験 | モバイル・アクセシビリティ | 4 モバイル / 5 a11y |
| 信頼 | 法令・ポリシー・フォームで安心させる | 6 信頼・ポリシー・フォーム |
| 攻め | 速さとCVで成果を出す | 7 パフォーマンス / 8 CRO / 9 計測 |
| 堅牢 | セキュリティ・エラー・正規化 | 10 セキュリティ・エラー |
| 運用 | 公開後も壊れない | 運用 / 検証 / デプロイ |
✅ 既に良かった土台(=最低ライン。新規でも必ず満たす)
前回プロジェクトで着手時点から品質が高く、そのまま踏襲すべきもの。
技術基盤
<head>を共通 Base レイアウトで一元管理。Props:title / description / path / ogType / ogImage / noindex / jsonLd- canonical を
site + pathで自動生成 - OGP / Twitter Card 完備:
og:image:width=1200/height=630、og:locale=ja_JP、twitter:card=summary_large_image - JSON-LD
@graph基底:Organization(+founder) /WebSite/Personを@idで相互参照 noindex制御を Props で持つ(thanks等)- GA4 は本番ドメイン限定の inline ガード(localhost/プレビューでは計測しない)
- フォント:
preconnect+display=swap - PWA/アイコン基礎:
site.webmanifest/theme-color/apple-touch-icon - Content Collections + Zod:
categoryはz.enum、pubDateはz.coerce.date()、draftフラグ - CI/CD: Firebase Hosting + GitHub Actions(PRプレビュー +
main本番) - URL一貫性:
trailingSlash:'always'+build.format:'directory' - デザイン基礎: clamp タイポ、CSS変数トークン
- カスタム404(
src/pages/404.astro)
信頼・ポリシー(前回サイトの強み。テンプレ流用で済ませない)
- プライバシーポリシーを実務水準で作り込む(§6 参照)。制定日/最終改定日を明記
- フッターに Privacy Policy リンクを常設(
Footer.astroの Company 欄) - 問い合わせフォームに同意チェック必須(プライバシーポリシーへのリンク付き)
- 問い合わせページのサイドに信頼要素(返信目安「2営業日」・プライバシー・連絡手段)= CROの安心材料
- thanks ページは
noindex(CV計測ポイントだが検索結果には出さない)
フォーム完成度(前回の型を踏襲)
- ネイティブ HTML5 バリデーション + JS
checkValidity()/reportValidity() - 二重送信防止(送信中
disabled+ 「送信中…」) - honeypot(隠しフィールド
website。入力があれば送信せず thanks へ=ボットを黙って弾く) - Google Forms へ
no-corsPOST +Promise.raceタイムアウト → 失敗でもthanksへ遷移 labelと入力の紐付け、必須/任意の明示
0. 前提設定(astro.config / 配信)
site: 'https://example.com'trailingSlash: 'always'+build: { format: 'directory' }- Firebase Hosting:
"trailingSlash": true(.xml/.txt/.icoはそのまま配信) - ビルド:
ASTRO_TELEMETRY_DISABLED=1 npm run build
1. SEO 構造 【守り】
- 全ページ:
title/meta description/ canonical / OGP / Twitter Card /lang="ja" - JSON-LD
@graph:- 全ページ:
Organization/WebSite/Person - 記事:
BlogPosting+BreadcrumbList - 一覧/カテゴリ/タグ/ポリシー:
WebPageorCollectionPage+BreadcrumbList
- 全ページ:
- 著者
sameAs: X/LinkedIn/note/Zenn 等(E-E-A-T)。URL はオーナー確認 - カテゴリ/タグは静的ページ(JSフィルタだけにしない)
getStaticPathsで/insights/category/[category]//insights/tag/[tag]/を生成- 日本語タグはスラッグマップ(
生成AI → generative-ai) - チップは
<a href>+ JSpreventDefault(プログレッシブエンハンスメント)
2. AIO・フィード・robots 【守り】
- llms.txt 動的生成(
src/pages/llms.txt.ts)。静的public/llms.txtは削除 - RSS:
@astrojs/rss+<link rel="alternate" type="application/rss+xml"> - サイトマップ:
@astrojs/sitemap(filterで thanks/rss/llms 除外)→/sitemap-index.xml - robots.txt:
Sitemap:明記、AIクローラAllow: /、/contact/thanks/はDisallow - Search Console: サイトマップは フルURL(
https://example.com/sitemap-index.xml)で送信。相対パスだけだと「無効」と出ることがある
3. 回遊性 【回遊】
- 前後記事ナビ(日付降順ソート)
- 文脈付きサービス導線(カテゴリ →
/services/#advertising等) - 関連記事は加点方式:
共有タグ*10 + 同カテゴリ、frontmatterrelated最優先 - カードグリッドは
PostGrid.astro等に集約
4. モバイル 【体験】
390px 幅で横スクロールゼロを必須検証。
- Grid:
1fr→minmax(0,1fr)+ 子にmin-width:0 - 広い表:
.twrap{overflow-x:auto}+ JS自動ラップ(二重防止) overflow-wrap:break-word、グリッドは 3→2→1 カラム
SPコンパクト化(フォーム・LP優先)
PCで問題なくても、SPでは装飾ブロックが長くなりフォーム/CVまで届かない。640px以下(または560px以下)で冗長要素を消し、余白を圧縮する。
問い合わせページ(contact.astro):
- サイドの信頼3点(メール相談・返信目安・プライバシー)を SPのみ
display:none - フォーム下の
fnoteと同意チェックのポリシーリンクで必要情報は維持 - ヒーロー・メインセクションの
paddingを CSS クラス化して SP で縮小(inlinestyleは上書きしづらい) - サイド見出しの
<br>を SP でdisplay:noneにして1行表示(PCは2行のまま)
@media (max-width:560px){
.contact-chero{padding:28px 0 12px}
.contact-main{padding:8px 0 56px}
.cside-list,.cside-mark{display:none}
.cside-h br{display:none}
}
トップページ / LP(index.astro):
- Connect the dots 等の 01〜03ステップ一覧(
.gp-steps)を SP で非表示 FILE / 01 — …等の補足行(.gp-note-h)も SP で非表示- セクション全体の
.sec{padding}を SP で36px 0程度に圧縮(デフォルト 52px+ は長い) - ヒーロー
.hleftの padding/gap も縮小
@media (max-width:640px){
.sec{padding:36px 0 !important}
.gp-steps,.gp-note-h{display:none}
.hleft{padding:32px 0 24px !important;gap:24px !important}
}
その他ページの SP 調整例:
- Insights おすすめ記事グリッド: 1カラム(横はみ出し防止)
- Cases KPI パネル: 3列→2列
- About 実績グリッド: 2列→1列
- 記事ページ
.alayout:grid-template-columns:minmax(0,1fr)+.prose{min-width:0}
原則: PCの情報設計は維持し、SPだけ「届くまでの距離」を短くする。消すブロックの代替導線(フォーム下・同意・フッター)を必ず残す。
5. アクセシビリティ 【体験】
- H1は1つ。装飾英字は
<p role="presentation" aria-hidden="true"> - 複製DOM(ティッカー等):
aria-hidden+tabindex="-1" - 装飾画像:
alt=""+aria-hidden text-wrap:balance、ナビ/フィルタは実リンク- 色コントラスト 4.5:1、:focus-visible を消さない
prefers-reduced-motionでアニメ停止- スキップリンク、フォーム
label紐付け
6. 信頼・ポリシー・フォーム 【信頼】
前回プロジェクトでこだわって作ったポリシー実装を踏襲する。テンプレの流用で済ませない。
プライバシーポリシー必須章立て(最低12項目)
| # | 章 | 内容 |
|---|---|---|
| 1 | 取得する情報 | フォーム入力・取引情報・Cookie/アクセスログ |
| 2 | 利用目的 | 問い合わせ対応・サービス提供・改善・分析・法令対応 |
| 3 | 第三者への提供 | 法令例外・同意困難時の保護 |
| 4 | 業務委託先への提供 | 委託と監督 |
| 5 | Cookie・外部送信 | 改正電気通信事業法の外部送信規律。送信先(例 Google LLC)・送信情報・利用目的を具体列挙、オプトアウト手段 |
| 6 | 広告配信データ | リターゲティング、ハッシュ化提供、国外第三者への同意確認 |
| 7 | AIツール業務利用 | 個人情報/機密を学習に使わせない、匿名化・学習不使用設定、社内ルール ← AI時代の差別化 |
| 8 | 安全管理措置 | 漏えい防止・アクセス制御 |
| 9 | 肖像権・著作権・免責 | 人物写真の同意、コンテンツ権利、外部リンク免責 |
| 10 | 開示・訂正・削除請求 | 本人確認と対応窓口 |
| 11 | 改定 | 重要変更時のサイト告知 |
| 12 | お問い合わせ窓口 | 事業者名 + フォームリンク |
ポリシーページの実装パターン
src/pages/privacy.astro、.proseで読みやすい本文(max-width:760px、line-height:2)- 制定日・最終改定日をページ上部に表示
- JSON-LD:
WebPage+BreadcrumbList(noindexにしない=信頼ページとして索引させる) - 窓口は
.contact-boxで視覚的に区切る - SP: 下部パディングを十分に(フッター重なり防止)
サイト全体での信頼導線
- フッター Company 欄に Privacy Policy 常設
- 問い合わせフォーム:
<label class="consent"><input required> <a href="/privacy/">プライバシーポリシー</a>に同意</label> - 問い合わせサイド: 「安心のプライバシー」「2営業日以内に返信」を並べる(PC向け。SPでは §4 のコンパクト化で非表示可)
- thanks ページ:
noindex+ 受付完了メッセージ(CV計測ポイント) - GA4 を入れる時点で §5 の外部送信明示が必須(ポリシーと実装の整合)
フォーム追加要件(土台に上乗せ)
- 送信基盤: Google Forms(簡易)/ Formspree / Firebase Functions(自動返信・Slack通知)
- 送信失敗時のフォールバック(メール窓口併記)
- 物販・有料申込があれば 特定商取引法・利用規約を追加
ボット・スパム対策(段階的に上げる)【堅牢】
公開直後の海外1件ずつのアクセスは、クローラ・スキャナで異常とは限らない。フォームスパムだけ段階的に対処する。
| 段階 | 条件 | 対策 | コスト |
|---|---|---|---|
| 1(初期) | 公開時点 | honeypot | ほぼゼロ |
| 2 | スパムが週数件以上続く | Cloudflare Turnstile or reCAPTCHA | 低(キー取得のみ) |
| 3 | 大量スパム・攻撃的スキャン | Cloudflare(WAF/CDN/ボット管理) | DNS変更あり |
段階1 honeypot 実装パターン(contact.astro):
<div class="hp" aria-hidden="true">
<label for="website">Website</label>
<input type="text" name="website" id="website" tabindex="-1" autocomplete="off" />
</div>
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
const hp = form.querySelector('input[name=website]');
if (hp instanceof HTMLInputElement && hp.value.trim()) {
window.location.href = '/contact/thanks/'; return; // 送信せず黙って弾く
}
display:noneは避ける(一部ボットがスキップするため)- 弾いたときも thanks へ遷移させる(ボットに「弾かれた」と悟らせない)
段階2以降の判断基準:
- Google Forms に意味不明な送信が週数件以上
- 同じIP/文言の連続送信
- フォーム以外(メール直スパム)も増えたら段階3を検討
サイト閲覧ボットについて(別問題):
robots.txtで AI クローラは 意図的に Allow(AIO対策)。悪性ボットのブロックは段階3(WAF)で- GA4 の国別1件ずつは公開直後では正常範囲。GA4 は既知ボット除外あり(完全ではない)
7. パフォーマンス / Core Web Vitals 【攻め】
- 画像: Astro
<Image>で WebP/AVIF、width/height必須(CLS防止)。hero はfetchpriority="high"、他はloading="lazy" - LCP: ファーストビュー画像/フォントを
preload - フォント: 過剰なウェイト読み込みを避ける
- 目安: LCP < 2.5s / INP < 200ms / CLS < 0.1。Lighthouse(モバイル)計測
8. コンバージョン設計(LP / CRO) 【攻め】
- ファーストビュー: 誰の何を解決するか 1文 + 主要CTA1つ
- 社会的証明(実績数値・ロゴ・声)+ 不安解消(FAQ・料金・返信目安)
- CTA反復配置、フォーム項目は最小限
- 前回の良い型: 問い合わせサイドの信頼3点セット(§6)
9. 計測(GA4 イベント / CV) 【攻め】
- CVイベント: フォーム送信(thanks到達)・電話タップ・CTAクリック・スクロール到達
- thanks 到達を キーイベント(コンバージョン) に設定
- UTM運用ルール、Google Search Console 登録 + sitemap送信
- 同意が要る地域向け: Consent Mode v2、タグ増設時は GTM検討
10. セキュリティ・エラー・正規化 【堅牢】
firebase.jsonheaders:HSTS/X-Content-Type-Options/Referrer-Policy/Permissions-Policy/(可能なら)CSP- カスタム404、旧URLは
redirectsでリダイレクトマップ - www ↔ apex 正規化を決める(保留すると重複の元)
npm auditを公開前に確認
6b. ファビコン 【守り】
Google検索で箱アイコンになる典型原因: 非正方形 / 48px未満 / favicon.ico 404。
- 正方形ソースから 16/32/48 の
.icoを生成(scripts/make-favicon.mjs) <head>:favicon.ico+favicon-32.png+favicon-48.png+icon-192.png+apple-touch-icon- 反映は再クロール後 数日〜数週間
7b. その他実装ディテール
- メール難読化:
data-u/data-d+ JS でmailto:復元 - CTA/サービスカードは実在ページ・アンカーに統一
運用(公開後)
- アップタイム監視 / Sentry等
- 検証拡張: Lighthouse / axe / Rich Results Test / リンク切れ / 実機
- 独自ドメインメール: SPF / DKIM / DMARC
検証(デプロイ前)
- [ ] ビルド成功、dist に sitemap/rss/llms/favicon がある
- [ ] 390px 横スクロールなし
- [ ] SP: 問い合わせ・トップで冗長ブロック非表示・余白圧縮(フォーム/CVまで届くか)
- [ ] 記事: 前後ナビ・関連記事・サービス導線
- [ ] Lighthouse(モバイル) LCP/INP/CLS 目安内
- [ ] フォーム: 同意必須・二重送信防止・**honeypot**・thanks遷移
- [ ] GA4 CVイベント発火、GSC sitemap送信
- [ ] プライバシーポリシー: 12章立て・外部送信明示・AI利用方針・制定改定日
- [ ] フッター/フォーム/問い合わせサイドにポリシー導線
- [ ] favicon正方形、セキュリティヘッダ、404、prefers-reduced-motion
390px はみ出しチェック:
(() => {
const vw = document.documentElement.clientWidth;
const over = [];
document.querySelectorAll('body *').forEach(el => {
const r = el.getBoundingClientRect();
if (r.right > vw + 1) over.push({ tag: el.tagName, cls: (el.className||'').toString().slice(0,30), right: Math.round(r.right) });
});
return { viewport: vw, docScrollWidth: document.documentElement.scrollWidth,
horizontalOverflow: document.documentElement.scrollWidth > vw + 1, offenders: over.slice(0,15) };
})()
サイト未実装でも次回チェックに残す項目
現サイトでは意図的に後回しにしてよいもの(スキルには残す):
- GA4 CVイベント / thanks をキーイベント化
firebase.jsonセキュリティヘッダprefers-reduced-motion- 著者 JSON-LD の
sameAs(外部URL確定後) - Astro
<Image>による画像最適化 - 記事本文内の文脈リンク(編集判断)
依存の落とし穴
@astrojs/sitemap: Astro 4 では@3.2.1に固定(3.7+ は Astro 5 専用でビルド落ち)- GitHub Actions:
checkout@v5/setup-node@v5、Node 22
デプロイ(GitHub → Firebase)
mainpush で本番、PR でプレビュー- コミットメールは GitHub noreply(
GH007回避) - サービスアカウント JSON は
.gitignore
Additional resources
- ファビコン生成: scripts/make-favicon.mjs