// 完整的 Cloudflare Workers A/B 測試代碼
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
// 獲取用戶的測試版本
const cookie = request.headers.get('Cookie')
let variant = getVariantFromCookie(cookie)
if (!variant) {
// 50/50 分割 (可調整比例)
variant = Math.random() < 0.5 ? 'A' : 'B'
}
// 根據版本修改請求
let targetUrl = url.toString()
if (variant === 'B') {
// 方案1: 重寫 URL 路徑
url.pathname = '/test' + url.pathname
targetUrl = url.toString()
// 方案2: 或者指向不同的後端
// targetUrl = 'https://test.yourdomain.com' + url.pathname + url.search
}
// 創建新的請求,添加測試版本標頭
const modifiedRequest = new Request(targetUrl, {
method: request.method,
headers: request.headers,
body: request.body
})
// 添加自定義標頭,讓後端知道是哪個測試版本
modifiedRequest.headers.set('X-AB-Test-Variant', variant)
try {
// 發送請求到後端
const response = await fetch(modifiedRequest)
// 創建新的響應,保持原有內容
const newResponse = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: response.headers
})
// 設置 cookie 保持用戶在同一測試組
const cookieValue = `ab_test=${variant}; Path=/; HttpOnly; SameSite=Strict; Max-Age=2592000` // 30天
newResponse.headers.set('Set-Cookie', cookieValue)
// 添加測試版本到響應標頭(用於分析)
newResponse.headers.set('X-AB-Test-Variant', variant)
return newResponse
} catch (error) {
// 錯誤處理:如果測試版本失敗,回退到原版本
if (variant === 'B') {
console.log('Test version failed, falling back to original')
const fallbackResponse = await fetch(request)
const newResponse = new Response(fallbackResponse.body, fallbackResponse)
newResponse.headers.set('Set-Cookie', `ab_test=A; Path=/; HttpOnly; SameSite=Strict; Max-Age=2592000`)
return newResponse
}
// 如果原版本也失敗,返回錯誤
return new Response('Service temporarily unavailable', { status: 503 })
}
}
// 從 cookie 中提取測試版本
function getVariantFromCookie(cookieHeader) {
if (!cookieHeader) return null
const cookies = cookieHeader.split(';')
for (const cookie of cookies) {
const [name, value] = cookie.trim().split('=')
if (name === 'ab_test') {
return value === 'A' || value === 'B' ? value : null
}
}
return null
}
// 可選:添加更複雜的流量分割邏輯
function getVariantWithAdvancedLogic(request) {
const url = new URL(request.url)
const userAgent = request.headers.get('User-Agent') || ''
const country = request.cf?.country || 'Unknown'
// 排除搜索引擎爬蟲
if (userAgent.includes('Googlebot') || userAgent.includes('bingbot')) {
return 'A'
}
// 特定國家使用不同比例
if (country === 'US') {
return Math.random() < 0.3 ? 'B' : 'A' // 30% 看到 B 版本
}
// 特定頁面不參與測試
if (url.pathname.startsWith('/admin') || url.pathname.startsWith('/api')) {
return 'A'
}
// 默認 50/50 分割
return Math.random() < 0.5 ? 'A' : 'B'
}
// 可選:記錄測試數據到 KV Storage
async function logTestData(variant, url, userAgent) {
const key = `ab_test_${Date.now()}_${Math.random()}`
const data = {
variant,
url: url.toString(),
userAgent,
timestamp: new Date().toISOString()
}
// 需要先在 Cloudflare 創建 KV namespace
// await YOUR_KV_NAMESPACE.put(key, JSON.stringify(data))
}
Cloudflare A/B Test 部署步驟:
- 登入 Cloudflare Dashboard
- 左側選單 → Workers & Pages
- 點擊 "Create application"
- 選擇 "Create Worker"
- 撰寫A/B測試程式碼(它是一段 java script)
- 點擊 "Deploy"
設置路由:
部署後還需要設置路由讓 Worker 生效:
- 在 Worker 頁面點擊 "Settings"
- 選擇 "Triggers" 標籤
- 點擊 "Add route"
-
輸入:
yourdomain.com/*
- 選擇你的網域
測試方法:
訪問你的網站,檢查:
- 瀏覽器開發者工具 → Network → Response Headers
- 應該看到
X-AB-Test-Variant: A
或B
- Cookie 中應該有
ab_test=A
或ab_test=B
注意事項:
- 確保你的網域已經在 Cloudflare 託管
- 第一次部署可能需要幾分鐘生效
- 可以在 "Quick Edit" 中修改代碼