【问题标题】:Cloudflare sessionsCloudflare 会话
【发布时间】:2019-09-19 22:16:48
【问题描述】:

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

当一个新会话开始时,查看 utm_source/utm_medium 查询字符串值以及引用者。根据显示网站的不同电话号码,例如 google cpc、bing cpc、google organic、bing organic 会有不同的号码。

然后,每个号码的呼叫次数应表明是哪个流量来源产生了呼叫。

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

有解决办法吗?有没有办法在 cloudflare 本身上做到这一点,也许使用它的“工人”?

谢谢

【问题讨论】:

    标签: cloudflare cloudflare-workers


    【解决方案1】:

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2017-04-21
      • 2014-10-08
      • 1970-01-01
      • 2021-10-17
      • 2021-04-08
      • 1970-01-01
      相关资源
      最近更新 更多