Skip to content

GTM script update#24

Merged
danielsitek merged 5 commits intomasterfrom
feature/ds-gtm-script-update
Apr 28, 2025
Merged

GTM script update#24
danielsitek merged 5 commits intomasterfrom
feature/ds-gtm-script-update

Conversation

@danielsitek
Copy link
Copy Markdown
Owner

@danielsitek danielsitek commented Apr 28, 2025

Summary by CodeRabbit

  • New Features
    • A "Cookie Settings" link is now dynamically added to the page after a short delay, allowing users to access consent settings.
  • Enhancements
    • Consent management now includes additional categories for ad user data and ad personalization, improving control over marketing preferences.
    • Clicking the "Cookie Settings" link opens the consent modal for easier access to privacy options.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 28, 2025

Walkthrough

The changes introduce dynamic insertion of a "Cookie Settings" link into the HTML page after a short delay using a template and script. The GTM consent logic is updated to handle two additional consent categories, ad_user_data and ad_personalization, alongside existing categories. The code also adds a global click handler that opens the consent modal when the "Cookie Settings" link is clicked, and adjusts the structure of the global cookie consent settings object.

Changes

File(s) Change Summary
public/index.html Added a paragraph with ID dynamic-link-container, a template for the "Cookie Settings" link, and a script to inject the link after a 2-second delay.
src/gtm.ts Consolidated imports, extended consent logic to include ad_user_data and ad_personalization, updated the global consent settings structure, and added a global click event handler to open the consent modal when the link is clicked.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant DOM
    participant ConsentModal

    User->>Browser: Loads page
    Browser->>DOM: Fires DOMContentLoaded
    Browser->>DOM: Waits 2 seconds
    Browser->>DOM: Inserts "Cookie Settings" link into dynamic container

    User->>DOM: Clicks "Cookie Settings" link
    DOM->>Browser: Detects click event
    Browser->>ConsentModal: Calls CookieConsentModalOpen()
    ConsentModal->>User: Displays consent modal
Loading

Poem

🐰
A link appears, so quick, so sly,
"Cookie Settings" twinkles by.
With new consents now in the mix,
Ad data toggles—easy to fix!
Click the link, a modal springs—
Hopping through all cookie things!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
public/index.html (2)

197-208: Consider adding a fallback mechanism.

While the delayed content injection works, there's no fallback if the script fails to load or execute properly. Users would have no way to access cookie settings in such cases.

window.addEventListener('DOMContentLoaded', () => {
  setTimeout(() => {
    const container = document.getElementById('dynamic-link-container');
    const template = document.getElementById('cookie-settings-template');

    if (container && template?.content) {
      container.appendChild(template.content.cloneNode(true));
+    } else {
+      console.warn('Cookie settings link could not be added: container or template not found');
    }
  }, 2000);
});

199-207: Why delay the injection by 2 seconds?

The 2-second delay before injecting the cookie settings link seems arbitrary and may impact user experience. Consider reducing the delay or explaining its purpose with a comment.

window.addEventListener('DOMContentLoaded', () => {
-  setTimeout(() => {
+  // Short delay to ensure all other components are loaded
+  setTimeout(() => {
    const container = document.getElementById('dynamic-link-container');
    const template = document.getElementById('cookie-settings-template');

    if (container && template?.content) {
      container.appendChild(template.content.cloneNode(true));
    }
-  }, 2000);
+  }, 500); // Reduced from 2000ms for better user experience
});
src/gtm.ts (2)

159-169: Use optional chaining for null check.

The click handler implementation looks good, but could benefit from using optional chaining as suggested by the static analysis.

document.body.addEventListener('click', function (event) {
  const target = event.target as HTMLElement;

-  if (target && target.classList.contains('js-consent-open')) {
+  if (target?.classList.contains('js-consent-open')) {
    if (window.CookieConsentModalOpen) {
      event.preventDefault();
      window.CookieConsentModalOpen();
    }
  }
});
🧰 Tools
🪛 Biome (1.9.4)

[error] 163-163: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


164-167: Consider checking if CookieConsentModalOpen is a function.

The current implementation assumes window.CookieConsentModalOpen is a function if it exists. Adding a type check would make this more robust.

-  if (window.CookieConsentModalOpen) {
+  if (typeof window.CookieConsentModalOpen === 'function') {
    event.preventDefault();
    window.CookieConsentModalOpen();
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3520c4c and 58b1287.

📒 Files selected for processing (2)
  • public/index.html (2 hunks)
  • src/gtm.ts (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/gtm.ts (1)
src/config/index.ts (2)
  • GRANTED (37-37)
  • DENIED (36-36)
🪛 Biome (1.9.4)
src/gtm.ts

[error] 163-163: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (6)
public/index.html (2)

110-110: Added placeholder for dynamic content.

The empty paragraph with id="dynamic-link-container" serves as a target for dynamically injected content. This is a clean approach for DOM manipulation.


193-195: Good use of the template element for reusable content.

Using the <template> element is an efficient way to define content that will be cloned and injected later. The class js-consent-open appropriately matches the event handler in the GTM script.

src/gtm.ts (4)

43-44: Consistently applying new consent categories in the update handler.

The same consent categories are correctly applied in the consent update event handler, maintaining consistency with the default consent implementation.


57-58: Consistently adding consent categories to custom consent data.

Good implementation ensuring the new consent categories are also pushed to the custom consent from document section.


146-146:

Details

❓ Verification inconclusive

Verify impact of disabling the cross button.

Setting disableCross: true will remove the close (X) button from the consent modal. Ensure this is intended behavior and won't negatively impact user experience.


🏁 Script executed:

#!/bin/bash
# Check if there's documentation about disableCross in the codebase
rg -i "disableCross" --type md
# Also check for any related properties
rg -i "disable.*cross" --type ts
rg -i "disable.*button" --type ts

Length of output: 863


Confirm removal of the close (X) button in the consent modal

The disableCross flag is documented in README.md (boolean, default false) and wired through:

  • src/settings/default.ts (defaults to false)
  • src/services/settings-service.ts (merges window settings with defaults)
  • src/gtm.ts (overridden to true)
  • src/components/consent-button-close/consent-button-close.ts (hides the button when true)

Setting disableCross: true will remove the close button from the modal. Please verify that hiding the cross button aligns with the intended user experience.


17-18:

Details

✅ Verification successful

Added new consent categories for Google Ads.

The addition of ad_user_data and ad_personalization consent categories aligns with Google's latest consent mode requirements. Good implementation tying these to the existing marketing consent.

For more information about these categories, see Google's documentation on consent mode v2:


🌐 Web query:

What are ad_user_data and ad_personalization in Google consent mode v2?

💡 Result:

ad_user_data and ad_personalization in Google Consent Mode v2

Google Consent Mode v2 introduces two new consent parameters—ad_user_data and ad_personalization—specifically to address regulatory requirements and give users more granular control over how their data is handled for advertising purposes[4][6][8][9].

ad_user_data

  • This parameter indicates whether a user consents to their personal data being sent to Google for advertising-related purposes such as conversion tracking, campaign measurement, and reporting.
  • If a user grants consent, ad_user_data is set to "granted"; if not, it is set to "denied."
  • This setting governs whether personal data (as opposed to just cookie data) can be transmitted to Google services like Google Ads, Google Shopping, and Google Play for advertising use[4][8][10].

ad_personalization

  • This parameter controls whether a user consents to their data being used for personalizing ads—most notably for remarketing or tailored advertising campaigns.
  • Like ad_user_data, ad_personalization is either "granted" or "denied," depending on user consent.
  • Only when ad_personalization is granted can Google use the individual’s data for ad personalization, such as showing specific ads based on their previous activity or interests[4][8][10].

How They Differ from Previous Consent Mode Parameters

  • ad_storage and analytics_storage (existing parameters) only dictated whether cookies or app identifiers could be stored for advertising or analytics purposes.
  • ad_user_data and ad_personalization (new v2 parameters) relate to how personal data is used and shared by Google after it is collected, adding a downstream layer of user privacy protection[3][7][10].

Implementation Context

  • ad_user_data and ad_personalization are required to comply with the latest privacy laws in regions like the European Economic Area (EEA) and under the EU’s Digital Markets Act[4][7][10].
  • These parameters are implemented alongside cookie consent banners and Consent Management Platforms (CMPs). The user's choice on these banners is relayed to Google tags, enabling or restricting how data is processed and used for advertising[4][5][6].

Summary Table: Consent Mode v2 Parameters

Parameter Purpose User Choice
ad_storage Allows storage of cookies for advertising granted/denied
analytics_storage Allows storage of cookies for analytics granted/denied
ad_user_data Allows sending of user data to Google for advertising granted/denied
ad_personalization Allows personalized ads (e.g., remarketing) granted/denied

Key Points

  • ad_user_data: Governs permission to send personal data to Google for advertising uses.
  • ad_personalization: Governs whether user data can be used for personalized/remarketing ads.
  • Consent for both is managed through interactions with cookie banners and CMPs.
  • Implementation of both parameters is essential for continued use of Google advertising products in regulated regions[4][7][8][10].

Google Consent Mode v2, with these parameters, empowers site owners to align data usage to explicit user choices and increases user privacy control[4][9][10].

Citations:


✅ Approve: Correct implementation of ad_user_data & ad_personalization

  • File: src/gtm.ts (Lines 17–18)
      ad_user_data: defaultConsent.marketing ? GRANTED : DENIED,
      ad_personalization: defaultConsent.marketing ? GRANTED : DENIED,
  • ad_user_data governs whether personal data can be sent to Google for conversion tracking and reporting.
  • ad_personalization controls whether user data is used for remarketing and tailored ads.
  • Tying both to the existing marketing consent toggle is appropriate and aligns with Google Consent Mode v2 requirements.

No further changes required.

@danielsitek danielsitek merged commit 8e54686 into master Apr 28, 2025
12 checks passed
@danielsitek danielsitek deleted the feature/ds-gtm-script-update branch April 28, 2025 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant