首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Cloudflare会话

Cloudflare会话
EN

Stack Overflow用户
提问于 2019-05-01 18:16:45
回答 1查看 417关注 0票数 2

我想在我的网站上添加一个类似如下的功能:

当一个新会话启动时,查看utm_source/utm_medium查询字符串值和referrer。基于该显示不同的电话号码的网站,所以例如谷歌cpc,冰cpc,谷歌有机,冰有机将有不同的数字。

然后,对每个号码的呼叫数应该给出哪个业务源产生呼叫的指示。

问题是,因为我们使用的是clouldflare,所以如果从缓存中为用户提供了一个页面,那么在源服务器上就没有session_start事件。

有什么解决方案可以绕过这个问题吗?有没有办法在cloudflare本身做这件事,也许是使用它的“工人”?

谢谢

EN

回答 1

Stack Overflow用户

发布于 2019-05-08 08:13:22

可以使用Cloudflare工作者来实现这一点。worker脚本首先需要确定要显示的电话号码。这可以通过检查查询参数或cookie或请求的任何其他方面来完成。然后,worker脚本可以获取原始响应正文(从缓存或源服务器),并将所有出现的原始电话号码替换为新电话号码。

下面是一个执行此操作的worker脚本示例。要确定要显示的电话号码,它将首先检查查询参数,如您所提到的。当它看到utm_source查询参数时,它还将设置一个cookie,然后可以在所有后续请求中检查该cookie,以显示相同的电话号码。

代码语言:javascript
运行
复制
// 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;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55934706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档