Improve cross-domain tracking and add "Always" script category

Move linker config into gtag('config') call with accept_incoming and
decorate_forms for reliable cross-domain linking. Capture _gl parameter
in sessionStorage to preserve attribution across navigation. Add
referrer-based attribution replay fallback so GA4 reports source/medium
instead of (not set) when UTMs are absent. Add "Always" script category
that executes without waiting for consent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 12:09:49 +00:00
parent 868ed867e2
commit 7059c45e20
5 changed files with 43 additions and 5 deletions

View File

@@ -115,7 +115,6 @@ wait_for_update:c.wait_for_update||500
});
window.attCCHasConsent=false;
}
if(c.linker_domains&&c.linker_domains.length){g('set','linker',{'domains':c.linker_domains});}
if(!sessionStorage.getItem('att_cc_attr')){
var p=new URLSearchParams(window.location.search);
var a={
@@ -128,9 +127,10 @@ ut:p.get('utm_term')||'',
uo:p.get('utm_content')||'',
gc:p.get('gclid')||'',
dc:p.get('dclid')||'',
gl:p.get('_gl')||'',
t:Date.now()
};
if(a.r||a.us||a.gc){
if(a.r||a.us||a.gc||a.gl){
sessionStorage.setItem('att_cc_attr',JSON.stringify(a));
}
}
@@ -176,7 +176,7 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
if ( 'gtag' === $s['tracking_mode'] && ! empty( $s['ga4_measurement_id'] ) ) {
$id = esc_attr( $s['ga4_measurement_id'] );
return "<script async src=\"https://www.googletagmanager.com/gtag/js?id={$id}\"></script>
<script>window.attCCGtag('config','{$id}');</script>";
<script>(function(){var o={};var c=window.attCCConfig||{};if(c.linker_domains&&c.linker_domains.length){o.linker={domains:c.linker_domains,accept_incoming:true,decorate_forms:true};}window.attCCGtag('config','{$id}',o);})();</script>";
}
return '';

View File

@@ -97,7 +97,7 @@ class ATT_Consent_Scripts_Manager {
global $wpdb;
$table = self::table_name();
$allowed_categories = array( 'functional', 'analytics', 'marketing' );
$allowed_categories = array( 'always', 'functional', 'analytics', 'marketing' );
$allowed_placements = array( 'head', 'footer' );
$allowed_statuses = array( 'active', 'inactive' );
@@ -150,6 +150,7 @@ class ATT_Consent_Scripts_Manager {
public static function get_scripts_for_frontend() {
$scripts = self::get_scripts();
$grouped = array(
'always' => array( 'head' => array(), 'footer' => array() ),
'functional' => array( 'head' => array(), 'footer' => array() ),
'analytics' => array( 'head' => array(), 'footer' => array() ),
'marketing' => array( 'head' => array(), 'footer' => array() ),
@@ -193,6 +194,18 @@ class ATT_Consent_Scripts_Manager {
continue;
}
// "Always" scripts execute immediately without consent gating.
if ( 'always' === $script['category'] ) {
if ( preg_match( '/<script[\s>]/i', $snippet ) ) {
$output .= $snippet . "\n";
} elseif ( preg_match( '/^\s*</', $snippet ) ) {
$output .= $snippet . "\n";
} else {
$output .= '<script>' . $snippet . '</script>' . "\n";
}
continue;
}
// Check if snippet contains <script> tags.
if ( preg_match( '/<script[\s>]/i', $snippet ) ) {
// Rewrite each <script> tag to type="text/plain" with category attribute.