Astroでのファーストパーティトラッキング
APIルートを使用してAstroプロジェクトにファーストパーティプロキシをセットアップします。スタティックモードとSSRモードの両方で動作します。
難易度:簡単 - プロジェクトにAPIルートファイルを1つ追加するだけです。
なぜこれが機能するのか(同一オリジン)
このアプローチは、/api/_z/script.jsを使用します。これはWebサイトと同じオリジン上にあります。Firefox ETPおよび他のトラッキング保護は、クロスオリジンリクエストのみをブロックします。
- ブラウザが見るもの:
yourdomain.com/api/_z/script.js— 同一オリジン、クロスオリジンブロックなし - AstroのAPIルートがリクエストをZenovayサーバーにプロキシします(ブラウザはこれを見ません)
- トラッキング保護はすべてバイパスされます。なぜなら、リクエストはファーストパーティだからです
開始する前に
以下をご用意ください:
- Astroプロジェクト(v2.0以上推奨)
- Zenovayトラッキングコード(Domains → ご利用のドメイン → Generalに表示)
- SSRアダプター(Vercel、Netlify、Cloudflare、Node等)がインストール済み
トラッキングコードの形式
トラッキングコードは次のような形式です:ZV_XXXXXXXXXX
ZV_で始まる- その後に10文字(文字と数字)が続く
- 大文字と小文字を区別します - 正確にコピーしてください
例:ZV_Q8U0GYD70WR

スタティックサイト: output: 'static'を使用している場合、AstroのAPIルートは機能しません。ホスティングプラットフォームのプロキシを使用してください(Vercelリライト、Netlifyリダイレクト等)。
ステップ1:SSRを有効化する(まだの場合)
まず、Astroプロジェクトにアダプターを使用してSSRが有効になっていることを確認します。
Vercelの場合
npm install @astrojs/vercelimport { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server', // または部分的なSSRの場合は 'hybrid'
adapter: vercel(),
});Netlifyの場合
npm install @astrojs/netlifyimport { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'server',
adapter: netlify(),
});Cloudflareの場合
npm install @astrojs/cloudflareimport { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});Node.jsの場合
npm install @astrojs/nodeimport { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
}),
});ステップ2:プロキシAPIルートを作成する
Zenovayにリクエストをプロキシする、キャッチオールAPIルートを作成します:
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// キャッチオールパラメータからパスを構築する
const path = params.path || ''
const url = new URL(request.url)
const targetUrl = `https://api.zenovay.com/fp/${path}${url.search}`
// CORSプリフライトリクエストを処理する
if (request.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
})
}
try {
// 正確なジオロケーションのための実際のクライアントIPを取得する
const clientIP = request.headers.get('x-forwarded-for')?.split(',')[0]
|| request.headers.get('cf-connecting-ip')
|| request.headers.get('x-real-ip')
|| ''
// プロキシヘッダーを構築する
const headers = new Headers()
headers.set('Content-Type', request.headers.get('Content-Type') || 'application/json')
headers.set('X-Zenovay-Real-IP', clientIP)
// リクエストを転送する
const response = await fetch(targetUrl, {
method: request.method,
headers: headers,
body: request.method !== 'GET' ? await request.text() : undefined,
})
// CORSヘッダー付きのレスポンスを構築する
const responseHeaders = new Headers(response.headers)
responseHeaders.set('Access-Control-Allow-Origin', '*')
return new Response(response.body, {
status: response.status,
headers: responseHeaders,
})
} catch (error) {
console.error('Proxy error:', error)
return new Response(JSON.stringify({ error: 'Proxy error' }), {
status: 502,
headers: { 'Content-Type': 'application/json' },
})
}
}なぜ [...path].ts なのか? スプレッド構文は複数のパスセグメントをキャプチャするキャッチオールルートを作成します。つまり、/api/_z/script.js、/api/_z/e/CODE、および /api/_z/settings/CODE はすべてこのファイルにルーティングされます。
ステップ3:トラッキングスクリプトを追加する
トラッキングスクリプトをレイアウトに追加します:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<!-- Zenovay Analytics (First-Party Proxy) -->
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>重要: YOUR_TRACKING_CODEをZenovayダッシュボードから取得した実際のトラッキングコードに置き換えてください。
ステップ4:デプロイする
Astroプロジェクトを選択したプラットフォームにデプロイします:
# プロジェクトをビルドする
npm run build
# デプロイする(アダプターによって異なります)
# Vercel: vercel deploy
# Netlify: netlify deploy --prod
# Cloudflare: wrangler pages deploy distハイブリッドモード(推奨)
サイトのほとんどがスタティックですがプロキシが必要な場合は、ハイブリッドモードを使用してください:
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'hybrid', // デフォルトではスタティック、特定のルートではSSR
adapter: vercel(),
});次に、APIルートをサーバーレンダリング用にマークします:
// このルートのサーバーレンダリングを強制する
export const prerender = false;
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// ... プロキシコードの残り
}動作確認
ネットワークタブで確認
- デプロイされたサイトにアクセス
- DevTools(F12)を開く
- Network タブに移動
- ページをリロード
/api/_z/script.jsを探す
以下のように表示されるはずです:
- Status: 200
- Domain: ご利用のドメイン
- Response: JavaScriptコード
Firefoxでテスト
- Firefoxを開く
- Settings → Privacy & Security → Enhanced Tracking Protection: Strict
- サイトにアクセス
- スクリプトが正常に読み込まれることを確認
トラブルシューティング
APIルートで404エラー
原因: SSRが有効になっていないか、アダプターが構成されていません。
解決方法:
astro.config.mjsにoutput: 'server'またはoutput: 'hybrid'があることを確認してください- アダプターがインストール済みで構成されていることを確認してください
- ハイブリッドモードの場合、APIルートに
export const prerender = false;を追加してください
500エラー
原因: APIルートのシンタックスエラーまたはランタイム問題。
解決方法:
- サーバーログで詳細なエラーメッセージを確認してください
- TypeScriptの型が正しいことを確認してください
- すべてのインポートが利用可能であることを確認してください
スクリプトが読み込まれるがデータがない
原因: トラッキングコードのミスマッチ。
解決方法:
data-tracking-codeがZenovayダッシュボードのコードと一致していることを確認してください- ブラウザコンソールでJavaScriptエラーを確認してください
- ドメインがZenovayに登録されていることを確認してください
ジオロケーションが間違っている
原因: クライアントIPが正しく転送されていません。
解決方法: APIルートは複数のヘッダーを試します。プラットフォームが以下のいずれかを転送していることを確認してください:
x-forwarded-for(最も一般的)cf-connecting-ip(Cloudflare)x-real-ip(nginx)
スタティックサイトの代替案
output: 'static' を使用している場合、APIルートは使用できません。代わりにホスティングプラットフォームのプロキシを使用してください:
Vercel
{
"rewrites": [
{ "source": "/api/_z/:path*", "destination": "https://api.zenovay.com/fp/:path*" }
]
}Netlify
/api/_z/* https://api.zenovay.com/fp/:splat 200Cloudflare Pages
Cloudflare Pages Functionsを使用してください。Cloudflare Pagesガイドを参照してください。
完全な例
my-astro-site/
├── astro.config.mjs
├── src/
│ ├── layouts/
│ │ └── Layout.astro
│ └── pages/
│ ├── index.astro
│ └── api/
│ └── _z/
│ └── [...path].ts
└── package.jsonimport { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
});---
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{title}</title>
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>最終チェックリスト
完了する前に、以下のすべてを確認してください:
- Astro SSRが有効になっている(またはスタティックサイトプラットフォームリライトを使用している)
- APIルートファイルが
src/pages/api/_z/[...path].tsに存在する -
export const prerender = falseが設定されている(ハイブリッドモード) - スクリプトタグが
/api/_z/script.jsを使用している(直接Zenovay URLではない) -
data-tracking-code属性に正しいトラッキングコードが含まれている - プロジェクトがデプロイされている(ローカル実行のみではない)
- Enhanced Tracking ProtectionをStrictに設定してFirefoxでテスト済み
- Zenovayダッシュボードに訪問が表示されている
次のステップ
- カスタムイベント - ユーザーインタラクションを追跡する
- 訪問者識別 - 分析をユーザーにリンクする
- トラブルシューティング - 問題の解決方法