Работники Cloudflare могут быть использованы для этого. Рабочий сценарий сначала должен определить, какой номер телефона показывать. Это можно сделать, проверив параметры запроса, файл cookie или любой другой аспект запроса. Затем рабочий сценарий может взять исходное тело ответа (из кэша или исходного сервера) и заменить все вхождения исходного номера телефона новым номером телефона.
Вот пример рабочего сценария, который делает это. Чтобы определить, какой номер телефона показывать, он сначала проверит параметры запроса, как вы упомянули. Когда он видит параметр запроса utm_source
, он также устанавливает 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;
}