nystudio107 / craft-seomatic

SEOmatic facilitates modern SEO best practices & implementation for Craft CMS 3. It is a turnkey SEO system that is comprehensive, powerful, and flexible.
https://nystudio107.com/plugins/seomatic
Other
162 stars 68 forks source link

Positioning of GTM code #1426

Open robzor opened 4 months ago

robzor commented 4 months ago

Question

Hi there,

I am trying to control the source order of the GTM script element in the section of my template. It appears that SEOmatic always injects right before the closing </head> tag.

I am trying to do this to implement the CookieBot auto mode along with Google Consent Mode and GTM, which requires a specific source order:

Ensure that the following scripts are the first on the page to load, in this exact order:

  • Google Consent Mode
  • Google Tag Manager
  • Cookiebot CMP (with automatic cookie blocking)

This is my current code:

    {#
      GTM, CookieBot and Google Consent Mode implementation
      Note: The source order is important!
     #}
    {# Enable Google Consent Mode #}
    <script data-cookieconsent="ignore">
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
      gtag("consent", "default", {
        ad_personalization: "denied",
        ad_storage: "denied",
        ad_user_data: "denied",
        analytics_storage: "denied",
        functionality_storage: "denied",
        personalization_storage: "denied",
        security_storage: "granted",
        wait_for_update: 500,
      });
      gtag("set", "ads_data_redaction", true);
      gtag("set", "url_passthrough", true);
    </script>

    {# Force rendering of GTM script in test environment #}
    {% if getenv('CRAFT_ENVIRONMENT') in ['staging', 'dev'] %}
      {% do seomatic.script.get('googleTagManager').include(true) %}
    {% endif %}

    {# CookieBot.com script injection (and implement consentmode) #}
    {{ craft.cookiebot.dialogScript()|replace('"auto"', '"auto" data-consentmode-defaults="disabled"')|raw }}

On a dev/staging environment, the GTM script from SEOMatic gets placed after the CookieBot code in the source HTML instead of before it, making it the in 3rd place instead of 2nd. (I know that on Production I would have to first disable the rendering of the script then grab it again)

Is it possible to make the {% do %} tag respect where it is placed in the source order of the template? Or is there another tag/function I can use so that I have full control of the order?

Thanks in advance for any help you might be able to give!

robzor commented 4 months ago

Ah i think this might be a duplicate of #1417

robzor commented 4 months ago

Your solution in #1417 was to tweak the GA script in the tracking scripts area, but because we do not have access to the wrapping <script> tag in that config area I don't think this is going to work here.

I'm struggling to work out how to actually just render the GTM tag inbetween those 2 tags.

robzor commented 4 months ago

Ok, so i've got to this:

{% set gtmSEOMatic = seomatic.script.render('googleTagManager')|json_decode %}
{{ gtmSEOMatic.script|raw }}

With automatic rendering disabled. Ideally I wouldn't want to disable automatic rendering though, so open to your ideas/suggestions on this one.

The .script renders both the head and the body script areas though, which adds an <iframe> into the <head> area, which is obviously not valid HTML :(

Maybe it would be good if you could add another node to the JSON of headScript (as you already have the bodyScript node on that array)?

It would be great to be able to do something like (with automatic rendering turned on):

in the <head>

{# Disable automatic placement of GTM script #}
{% do seomatic.script.get('googleTagManager').include(false) %}

{# Grab SEOMatic GTM script object #}
{{ seomatic.script.render('googleTagManager')|json_decode }}

{# Output head portion of SEOMatic GTM script object #}
{{ gtmSEOMatic.headScript|raw }}

in the <body>

{# Output body portion of SEOMatic GTM script object #}
{{ gtmSEOMatic.bodyScript|raw }}

But currently, the render() function will return nothing if I have set include() to false. (and ofc headScript doesn't actually exist :))

khalwat commented 4 months ago

Your solution in https://github.com/nystudio107/craft-seomatic/issues/1417 was to tweak the GA script in the tracking scripts area, but because we do not have access to the wrapping Githubissues.

  • Githubissues is a development platform for aggregating issues.