Cloudflare 工作人员可用于完成此任务。工作人员脚本首先需要确定要显示的电话号码。这可以通过检查查询参数或 cookie 或请求的任何其他方面来完成。然后工作脚本可以获取原始响应正文(来自缓存或原始服务器)并将所有出现的原始电话号码替换为新电话号码。
这是一个执行此操作的示例工作脚本。如您所述,要确定要显示哪个电话号码,它将首先检查查询参数。当它看到utm_source
查询参数时,它还将设置一个 cookie,然后可以在所有后续请求中检查该 cookie 以显示相同的电话号码。
// The name of the cookie that will be used to determine which phone number to show
const cookieName = "phone_num_id";
// The list of all phone numbers to use
const phoneNumbers = [
{
id: "google-cpc",
utmSource: "google",
utmMedium: "cpc",
phoneNumber: "222-222-2222"
},
{
id: "bing-cpc",
utmSource: "bing",
utmMedium: "cpc",
phoneNumber: "333-333-3333"
}
];
// This adds a "fetch" event listener which will be called for all incoming requests
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
// Forward the incoming request and get the original response. If Cloudflare has already cached
// this request, this will return the cached response, otherwise it will make the request to
// the origin
let response = await fetch(request);
// Check the content type of the response and fallback to an empty string
// if there is no content-type header
let contentType = response.headers.get("content-type") || "";
// We're only interested in changing respones that have a content-type starting
// with "text/html". Anything else will be returned without any modifications
if (/^text\/html/.test(contentType)) {
// `newPhoneNumberData` will be the new phone number to show (if any)
let newPhoneNumberData;
// searchParams are the query parameters for this request
let searchParams = new URL(request.url).searchParams;
// If the request has a `utm_source` query param, use that to determine which phone number to show
if (searchParams.has("utm_source")) {
let utmSource = searchParams.get("utm_source") || "";
let utmMedium = searchParams.get("utm_medium") || "";
// Lookup the phone number based on the `utmSource` and `utmMedium`
newPhoneNumberData = phoneNumbers.find(
phoneNumber =>
phoneNumber.utmSource === utmSource &&
phoneNumber.utmMedium === utmMedium
);
// If we found a match, set a cookie so that subsequent requests get the same phone number
if (newPhoneNumberData) {
// In order to modify the response headers, we first have to duplicate the response
// so that it becomes mutable
response = new Response(response.body, response);
// Now set a cookie with the id of the new phone number to use. You should modify the properties
// of the cookie for your use case. See this page for more information:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
response.headers.append(
"Set-Cookie",
`${cookieName}=${newPhoneNumberData.id}; Max-Age=2147483647`
);
}
}
// If we weren't able to determine the new phone number based on the query params, try
// checking the cookies next
if (!newPhoneNumberData) {
let cookieHeader = request.headers.get("cookie") || "";
// split each of the cookies and remove leading/trailing whitespace
let cookies = cookieHeader.split(";").map(str => str.trim());
// Find the phone number cookie
let phoneNumberCookieString = cookies.find(cookieString =>
cookieString.startsWith(`${cookieName}=`)
);
// If the request has the phone number cookie, use that
if (phoneNumberCookieString) {
// Extract the phone number id from the cookie
const phoneNumberId = phoneNumberCookieString.split("=")[1];
// Lookup the phone number data based on the ID
newPhoneNumberData = phoneNumbers.find(
phoneNumber => phoneNumber.id === phoneNumberId
);
}
}
// If we found a matching phone number to use, now we'll need to replace all occurences
// of the original phone number with the new one before returning the response
if (newPhoneNumberData) {
// Get the original response body
let responseBody = await response.text();
// Use a regex with the `g` flag to find/replace all occurences of the original phone number.
// This would look for a phone number like "(111)-111-1111" but you can modify this to fit
// however your original phone number appears
responseBody = responseBody.replace(
/\(?111\)?[-\s]*111[-\s]*1111/g,
newPhoneNumberData.phoneNumber
);
// Create a new response with the updated responseBody. We also pass the original `response` as the
// second argument in order to copy all other properties from the original response (status, headers, etc)
response = new Response(responseBody, response);
}
}
return response;
}