Git Product home page Git Product logo

Comments (13)

j0Shi82 avatar j0Shi82 commented on July 1, 2024 1

@maruthasalamr Unfortunately I'm a bit busy at the moment, but I'll try to look into it in the coming days.

from partytown.

j0Shi82 avatar j0Shi82 commented on July 1, 2024

The code snippet is hard to read, but I think you might indeed be missing a closing bracket in your dangerouslySetInnerHTML:

dangerouslySetInnerHTML={{
__html:(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XXXXXXXX')
}}

Notice the trailing bracket after 'GTM-XXXXXXXX'. It's missing in your code above and hence leading to the JavaScript error.

Again: GTM preview is not possible at the moment with Partytown. For more information refer to #72.

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82 thanks now the error is gone but how to fix the CORS error
can please help on this ?
image

image

from partytown.

j0Shi82 avatar j0Shi82 commented on July 1, 2024

Sure. As mentioned in the docs, requests from within a Web Worker require the correct CORS headers. It's a security measure that all modern browsers implement.

Apparently, CookieBot does not serve their assets with CORS headers. What you can do is host the script yourself (I have no experience with Gatsby, but there surely is a public folder you can work with). In case the script is dynamic and you have to get it from the vendor directly, you will need to set up a proxy as described here.

Cloudflare offers 100k requests for free (https://developers.cloudflare.com/workers/platform/pricing/), but you can obviously use whatever service you wish or deploy your own server that proxies the requests with the correct CORS header. The Cloudflare worker could look like this:

export default {
  async fetch(request) {
    // node_modules/itty-router/dist/itty-router.min.mjs
    function e({ base: t = "", routes: n = [] } = {}) {
      return { __proto__: new Proxy({}, { get: (e2, a, o) => (e3, ...r) => n.push([a.toUpperCase(), RegExp(`^${(t + e3).replace(/(\/?)\*/g, "($1.*)?").replace(/\/$/, "").replace(/:(\w+)(\?)?(\.)?/g, "$2(?<$1>[^/]+)$2$3").replace(/\.(?=[\w(])/, "\\.").replace(/\)\.\?\(([^\[]+)\[\^/g, "?)\\.?($1(?<=\\.)[^\\.")}/*$`), r]) && o }), routes: n, async handle(e2, ...r) {
        let a, o, t2 = new URL(e2.url);
        e2.query = Object.fromEntries(t2.searchParams);
        for (var [p, s, u] of n)
          if ((p === e2.method || "ALL" === p) && (o = t2.pathname.match(s))) {
            e2.params = o.groups;
            for (var c of u)
              if (void 0 !== (a = await c(e2.proxy || e2, ...r)))
                return a;
          }
      } };
    }

    var router = e();

    router.get("/api/partytown/proxy", async (req) => {
      let url = new URL(req.url);

      if (!url.searchParams.has('url')) {
        return new Response("Invalid", { status: 400 });
      }

      const decodedUrl = decodeURIComponent(url.searchParams.get('url'));
      
      const res = await fetch(decodedUrl);
      const newHeaders = new Headers(res.headers)
      newHeaders.set('access-control-allow-origin', '*');
      const newResponse = new Response(res.body, {
        headers: newHeaders
      })  
      return newResponse;
    });
    router.all("*", () => new Response("Not Found.", { status: 404 }));
    
    return router.handle(request);
  }
};

Then setup the resolveUrl option in the Partytown config:

resolveUrl: (url, location, type) => {
  if (type === 'script' && url.hostname.includes('cookiebot')) {
    const proxyUrl = new URL('/api/partytown/proxy', YOUR_WORKER_DOMAIN);
    proxyUrl.searchParams.append('url', url.href);
    return proxyUrl;
  }
}

You might need to adjust the snippet to fit your needs, but it should poke you into the right direction, I hope. Happy coding!

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82 thank you for your quick response i have added the proxy in partytown config and I'm using AWS Cloudfront
distribution for my website hosting
Now the CORS error is fixed but 404 error comes. please help me on this
This is my Partytown gatsby configuration

<Partytown
      key="partytown"
      resolveUrl={(url, location, type) => {
        let proxyUrl;
        if (type === 'script' && url.hostname.includes('cookiebot')) {
          proxyUrl = new URL('/api/partytown/proxy', 'http://localhost:9000/');
          proxyUrl.searchParams.append('url', url.href);
          return proxyUrl;
        }
        if (type === 'script' && url.hostname.includes('analytics')) {
          proxyUrl = new URL('/api/partytown/proxy', 'http://localhost:9000/');
          proxyUrl.searchParams.append('url', url.href);
          return proxyUrl;
        }
        return url;
      }}
      debug={true}
      forward={['dataLayer.push']}
    />,
    <script
      key="plugin-google-tagmanager"
      type="text/partytown"
      dangerouslySetInnerHTML={{
        __html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','GTM-MKPX3TV4');`,
      }}
    />

This is error i got in network tab

image image

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82 can we do using cloudfront ?

Sure. As mentioned in the docs, requests from within a Web Worker require the correct CORS headers. It's a security measure that all modern browsers implement.

Apparently, CookieBot does not serve their assets with CORS headers. What you can do is host the script yourself (I have no experience with Gatsby, but there surely is a public folder you can work with). In case the script is dynamic and you have to get it from the vendor directly, you will need to set up a proxy as described here.

Cloudflare offers 100k requests for free (https://developers.cloudflare.com/workers/platform/pricing/), but you can obviously use whatever service you wish or deploy your own server that proxies the requests with the correct CORS header. The Cloudflare worker could look like this:

export default {
  async fetch(request) {
    // node_modules/itty-router/dist/itty-router.min.mjs
    function e({ base: t = "", routes: n = [] } = {}) {
      return { __proto__: new Proxy({}, { get: (e2, a, o) => (e3, ...r) => n.push([a.toUpperCase(), RegExp(`^${(t + e3).replace(/(\/?)\*/g, "($1.*)?").replace(/\/$/, "").replace(/:(\w+)(\?)?(\.)?/g, "$2(?<$1>[^/]+)$2$3").replace(/\.(?=[\w(])/, "\\.").replace(/\)\.\?\(([^\[]+)\[\^/g, "?)\\.?($1(?<=\\.)[^\\.")}/*$`), r]) && o }), routes: n, async handle(e2, ...r) {
        let a, o, t2 = new URL(e2.url);
        e2.query = Object.fromEntries(t2.searchParams);
        for (var [p, s, u] of n)
          if ((p === e2.method || "ALL" === p) && (o = t2.pathname.match(s))) {
            e2.params = o.groups;
            for (var c of u)
              if (void 0 !== (a = await c(e2.proxy || e2, ...r)))
                return a;
          }
      } };
    }

    var router = e();

    router.get("/api/partytown/proxy", async (req) => {
      let url = new URL(req.url);

      if (!url.searchParams.has('url')) {
        return new Response("Invalid", { status: 400 });
      }

      const decodedUrl = decodeURIComponent(url.searchParams.get('url'));
      
      const res = await fetch(decodedUrl);
      const newHeaders = new Headers(res.headers)
      newHeaders.set('access-control-allow-origin', '*');
      const newResponse = new Response(res.body, {
        headers: newHeaders
      })  
      return newResponse;
    });
    router.all("*", () => new Response("Not Found.", { status: 404 }));
    
    return router.handle(request);
  }
};

Then setup the resolveUrl option in the Partytown config:

resolveUrl: (url, location, type) => {
  if (type === 'script' && url.hostname.includes('cookiebot')) {
    const proxyUrl = new URL('/api/partytown/proxy', YOUR_WORKER_DOMAIN);
    proxyUrl.searchParams.append('url', url.href);
    return proxyUrl;
  }
}

You might need to adjust the snippet to fit your needs, but it should poke you into the right direction, I hope. Happy coding!

from partytown.

j0Shi82 avatar j0Shi82 commented on July 1, 2024

Cloudfront functions are JavaScript as well afaik. So you should be able to use the code snippet with small adjustments. A quick search revealed that Cloudfront functions may be limited to 1ms of CPU time. Not sure it's still up-to-date. But our production workers use 1.5ms of CPU time on average. So you might run a quota issue there.

Sorry I cannot assist more specifically. You will need to work with the Cloudfront docs to set up your proxy.

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82 thank you for your response
CORS error is fixed and I have updated CORS in cloudfront behaviours.

Can we take it to production without the seeing the triggers/events are tracked in GTM preview mode ?

from partytown.

j0Shi82 avatar j0Shi82 commented on July 1, 2024

What you can do to verify that the data is flowing is go into your connected Analytics account, monitor the live view, and refresh your page a couple times. In case events appear there, you should be ok. I personally always set up GTM without Partytown to be able to use the debug mode and then move it into the worker. Usually it works fine, but you should absolutely keep an eye on your connected vendors to make sure the data is coming in as expected. Remember Partytown is an open source beta so you'll always need to do maintenance yourself. 👍

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

Yes, I can able to preview the tags in GTM without partytown and once i move the GTM into the worker i'm not able to preview the tags. Also i check the real time data in GA4 i can able to see the events appear there.
Thanks for your quick response

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82

I'm using hubspot as tag which added in GTM so it is requesting for https://js.hs-analytics.net/analytics/1710241500000/000000.js but receiving 404 not found

This my proxy setup please help me on this

image
<Partytown
      key="partytown"
      resolveUrl={(url, location) => {
        if (url.hostname.includes('analytics')) {
          // Use a secure connection
          if (url?.protocol === 'http:') {
            url = new URL(url.href.replace('http', 'https'));
          }
          // Point to our proxied URL
          const proxyUrl = new URL(location.origin + '/__third-party-proxy');
          proxyUrl.searchParams.append('url', url.href);
          return proxyUrl;
        }
        return url;
      }}
      debug={true}
      forward={['dataLayer.push']}
    />

from partytown.

maruthasalamr avatar maruthasalamr commented on July 1, 2024

@j0Shi82
I have added the code in cloudfare worker and i have update config in partytown but still CORS issue occurs
can you please help on this ?

 <Partytown
      key="partytown"
      resolveUrl={(url,type) => {
        if (url?.protocol === 'http:') {
          url = new URL(url.href.replace('http', 'https'))
        }
          if (type === 'script' && url.hostname.includes('analytics')) {
            const proxyUrl = new URL('/api/partytown/proxy', 'https://reverse-proxy.maruthasalam-rajendran.workers.dev/');
            proxyUrl.searchParams.append('url', url.href);
            return proxyUrl;
          }

        return url;
      }}
      debug={true}
      forward={['dataLayer.push']}
    />
image image

from partytown.

totodot avatar totodot commented on July 1, 2024

@j0Shi82 any update. It's look similar to resolveUrl issue for Partytown react component
#553

from partytown.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.