メインコンテンツへスキップ
5分で読めます

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

HTMLタブ、Reactタブ、Next.jsタブ、およびファーストパーティタブを含むトラッキングスクリプトカードを表示。
トラッキングコードはDomains → ご利用のドメイン → Generalの下のファーストパーティタブにあります。

スタティックサイト: output: 'static'を使用している場合、AstroのAPIルートは機能しません。ホスティングプラットフォームのプロキシを使用してください(Vercelリライト、Netlifyリダイレクト等)。


ステップ1:SSRを有効化する(まだの場合)

まず、Astroプロジェクトにアダプターを使用してSSRが有効になっていることを確認します。

Vercelの場合

TerminalBash
npm install @astrojs/vercel
astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
output: 'server', // または部分的なSSRの場合は 'hybrid'
adapter: vercel(),
});

Netlifyの場合

TerminalBash
npm install @astrojs/netlify
astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';

export default defineConfig({
output: 'server',
adapter: netlify(),
});

Cloudflareの場合

TerminalBash
npm install @astrojs/cloudflare
astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
output: 'server',
adapter: cloudflare(),
});

Node.jsの場合

TerminalBash
npm install @astrojs/node
astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
output: 'server',
adapter: node({
  mode: 'standalone'
}),
});

ステップ2:プロキシAPIルートを作成する

Zenovayにリクエストをプロキシする、キャッチオールAPIルートを作成します:

src/pages/api/_z/[...path].tsTypeScript
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:トラッキングスクリプトを追加する

トラッキングスクリプトをレイアウトに追加します:

src/layouts/Layout.astroASTRO
---
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プロジェクトを選択したプラットフォームにデプロイします:

TerminalBash
# プロジェクトをビルドする
npm run build

# デプロイする(アダプターによって異なります)
# Vercel: vercel deploy
# Netlify: netlify deploy --prod
# Cloudflare: wrangler pages deploy dist

ハイブリッドモード(推奨)

サイトのほとんどがスタティックですがプロキシが必要な場合は、ハイブリッドモードを使用してください:

astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
output: 'hybrid', // デフォルトではスタティック、特定のルートではSSR
adapter: vercel(),
});

次に、APIルートをサーバーレンダリング用にマークします:

src/pages/api/_z/[...path].tsTypeScript
// このルートのサーバーレンダリングを強制する
export const prerender = false;

import type { APIRoute } from 'astro'

export const ALL: APIRoute = async ({ params, request }) => {
// ... プロキシコードの残り
}

動作確認

ネットワークタブで確認

  1. デプロイされたサイトにアクセス
  2. DevTools(F12)を開く
  3. Network タブに移動
  4. ページをリロード
  5. /api/_z/script.js を探す

以下のように表示されるはずです:

  • Status: 200
  • Domain: ご利用のドメイン
  • Response: JavaScriptコード

Firefoxでテスト

  1. Firefoxを開く
  2. Settings → Privacy & Security → Enhanced Tracking Protection: Strict
  3. サイトにアクセス
  4. スクリプトが正常に読み込まれることを確認

トラブルシューティング

APIルートで404エラー

原因: SSRが有効になっていないか、アダプターが構成されていません。

解決方法:

  1. astro.config.mjsoutput: 'server' または output: 'hybrid' があることを確認してください
  2. アダプターがインストール済みで構成されていることを確認してください
  3. ハイブリッドモードの場合、APIルートに export const prerender = false; を追加してください

500エラー

原因: APIルートのシンタックスエラーまたはランタイム問題。

解決方法:

  1. サーバーログで詳細なエラーメッセージを確認してください
  2. TypeScriptの型が正しいことを確認してください
  3. すべてのインポートが利用可能であることを確認してください

スクリプトが読み込まれるがデータがない

原因: トラッキングコードのミスマッチ。

解決方法:

  1. data-tracking-code がZenovayダッシュボードのコードと一致していることを確認してください
  2. ブラウザコンソールでJavaScriptエラーを確認してください
  3. ドメインがZenovayに登録されていることを確認してください

ジオロケーションが間違っている

原因: クライアントIPが正しく転送されていません。

解決方法: APIルートは複数のヘッダーを試します。プラットフォームが以下のいずれかを転送していることを確認してください:

  • x-forwarded-for (最も一般的)
  • cf-connecting-ip (Cloudflare)
  • x-real-ip (nginx)

スタティックサイトの代替案

output: 'static' を使用している場合、APIルートは使用できません。代わりにホスティングプラットフォームのプロキシを使用してください:

Vercel

vercel.jsonJSON
{
"rewrites": [
  { "source": "/api/_z/:path*", "destination": "https://api.zenovay.com/fp/:path*" }
]
}

Netlify

public/_redirectsTEXT
/api/_z/*  https://api.zenovay.com/fp/:splat  200

Cloudflare Pages

Cloudflare Pages Functionsを使用してください。Cloudflare Pagesガイドを参照してください。


完全な例

Project StructureTEXT
my-astro-site/
├── astro.config.mjs
├── src/
│   ├── layouts/
│   │   └── Layout.astro
│   └── pages/
│       ├── index.astro
│       └── api/
│           └── _z/
│               └── [...path].ts
└── package.json
astro.config.mjsJavaScript
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
output: 'hybrid',
adapter: vercel(),
});
src/layouts/Layout.astroASTRO
---
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ダッシュボードに訪問が表示されている

次のステップ

このページは役に立ちましたか?