Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically mark GA4 scripts as being PX-verified #7290

Merged
merged 36 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c8a5ed4
Add GA4 scripts sanitizer
thelovekesh Oct 10, 2022
91e57b9
Add AMP_GTag_Script_Sanitizer class in sanitizers
thelovekesh Oct 10, 2022
fa5bc0f
Add sandboxing options in the Option interface
thelovekesh Oct 10, 2022
86cdc26
Update sandboxing options to be used from Option interface
thelovekesh Oct 10, 2022
c8b6462
Update sandboxing options
thelovekesh Oct 10, 2022
59911c2
Update tests to use sandboxing level from Option interface
thelovekesh Oct 10, 2022
a03dd35
Update sandboxing service tests
thelovekesh Oct 10, 2022
a62b010
Update xpath to query gtag script tags more accurately
thelovekesh Oct 10, 2022
090b84c
Add test cases for AMP_GTag_Script_Sanitizer class
thelovekesh Oct 10, 2022
b6d5bae
Merge branch 'develop' into add/GA4-scripts-sanitizer
thelovekesh Oct 19, 2022
7c1cd64
Update comment for included `AMP_GTag_Script_Sanitizer` class in sani…
thelovekesh Oct 21, 2022
b88130f
Update xpath query for Google tag scripts
thelovekesh Oct 21, 2022
97b1053
Add deprecated tag on sandboxing service option keys constants
thelovekesh Oct 21, 2022
c47c831
Add space after class declaration
thelovekesh Oct 21, 2022
60a5ce8
Remove tear_down fixture as WordPress tests rollback the current data…
thelovekesh Oct 21, 2022
f6ba0a8
Remove setup fixture
thelovekesh Oct 21, 2022
5032593
Add constant to store gtag html markup
thelovekesh Oct 21, 2022
8d34d45
Update xpath query to be more specific
thelovekesh Oct 21, 2022
b28e9d3
Move tests to dataProvider
thelovekesh Oct 21, 2022
357f4cc
Add more script tags to make sure any non-gtag script tags are always…
thelovekesh Oct 21, 2022
74a3f9f
Merge branch 'develop' into add/GA4-scripts-sanitizer
thelovekesh Oct 21, 2022
8d13af0
Remove unused method
thelovekesh Oct 21, 2022
a1e9b6e
Add `@return` tag in dataProvider
thelovekesh Oct 21, 2022
3e7d2dc
Remove unused properties
thelovekesh Oct 21, 2022
0aca46e
Add more script tags for clear test cases
thelovekesh Oct 21, 2022
feb3910
Add assertions for scripts other then gtag scripts
thelovekesh Oct 21, 2022
df3ee7b
Add inline gtag event attrs as px verified attrs
thelovekesh Oct 25, 2022
1762657
Add test cases for px verified attrs with inline gtag event
thelovekesh Oct 25, 2022
ca84712
Merge branch 'develop' into add/GA4-scripts-sanitizer
thelovekesh Oct 25, 2022
5b0f6a4
Update xpath query to use starts-with while matching on* events
thelovekesh Oct 26, 2022
359bcc8
Update assertion method for finding a string match
thelovekesh Oct 26, 2022
e0a6906
Add early return if no gtag script is present
thelovekesh Oct 26, 2022
6bec836
Update xpath query in tests
thelovekesh Oct 26, 2022
d4b4bfd
Add test case when no gtag script is present in document
thelovekesh Oct 27, 2022
e50ee5b
qMerge branch 'develop' into add/GA4-scripts-sanitizer
thelovekesh Oct 27, 2022
aeacc33
Move up check for `DOMNodeList`
westonruter Oct 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions includes/sanitizers/class-amp-gtag-script-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,32 @@ public function sanitize() {
ValidationExemption::mark_node_as_px_verified( $script );
}
}

thelovekesh marked this conversation as resolved.
Show resolved Hide resolved
/**
* Mark inline gtag events as PX verified attributes.
*
* Such inline events can look like:
*
* onclick="gtag('event','click', { 'event_category':"click", 'event_label':"contactPage" })"
* onsubmit="gtag('event','submit', { 'event_category':"submit", 'event_label':"contactPage" })"
* onkeypress="gtag('event','keypress', { 'event_category':"keypress", 'event_label':"contactPage" })"
*/
$inline_events = $this->dom->xpath->query(
'
//@*[
substring(name(), 1, 2) = "on"
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved
and
name() != "on"
and
contains(., "gtag(")
]
'
);

if ( $inline_events instanceof DOMNodeList ) {
foreach ( $inline_events as $inline_event ) {
ValidationExemption::mark_node_as_px_verified( $inline_event );
}
}
}
}
35 changes: 34 additions & 1 deletion tests/php/test-class-amp-gtag-script-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use AmpProject\AmpWP\ValidationExemption;
use AmpProject\Dom\Document;
use AmpProject\Html\Tag;
use AmpProject\Dom\Element;
use AmpProject\AmpWP\Option;
use AmpProject\AmpWP\Tests\TestCase;

Expand All @@ -25,12 +26,19 @@ class AMP_GTag_Script_Sanitizer_Test extends TestCase {
*/
const SCRIPT_XPATH = '//script[ ( @async and starts-with( @src, "https://www.googletagmanager.com/gtag/js" ) ) or contains( text(), "function gtag(" ) ]';

/**
* XPath query to find inline gtag events.
*
* @var string
*/
const INLINE_GTAG_EVENT_XPATH = '//@*[ substring(name(), 1, 2) = "on" and name() != "on" and contains(., "gtag(") ]';

/**
* HTML markup with gtag script.
*
* @var string
*/
const GTAG_HTML_MARKUP = '<html><head></head><body><script async src="https://www.googletagmanager.com/gtag/js?id=xxxxxx"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","xxxxxx")</script><script src="https://example.com/pixel/js"></script><script>document.write("Hello world");</script></body></html>';
const GTAG_HTML_MARKUP = '<html><head></head><body><script async src="https://www.googletagmanager.com/gtag/js?id=xxxxxx"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","xxxxxx")</script><div><a href="/">Home</a><a href="/contact" onclick=\'gtag("event","click",{event_category:"click",event_label:"contactPage"})\'>Contact</a><form><input type="text" name="name" placeholder="Name"><button onsubmit=\'gtag("event","click",{event_category:"click",event_label:"contactPage"})\' onclick="submit()"></button><button type="reset" onclick="clear()">Reset</button></form></div><script src="https://example.com/pixel/js"></script><script>document.write("Hello world")</script></body></html>';
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved

/**
* Get data
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -85,16 +93,41 @@ public function test_sanitize( $enable_sandboxing, $sandboxing_level, $expect_px
$gtag_scripts = $dom->xpath->query( self::SCRIPT_XPATH );
$other_scripts = $dom->xpath->query( '//script[ not( @async and starts-with( @src, "https://www.googletagmanager.com/gtag/js" ) ) and not( contains( text(), "function gtag(" ) ) ]' );

// Gtag scripts.
$this->assertCount( 2, $gtag_scripts );
$this->assertInstanceof( DOMNodeList::class, $gtag_scripts );
foreach ( $gtag_scripts as $script ) {
$this->assertInstanceof( Element::class, $script );
$this->assertSame( Tag::SCRIPT, $script->tagName );
$this->assertEquals( $expect_px_verified, ValidationExemption::is_px_verified_for_node( $script ) );
}
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved

$this->assertCount( 2, $other_scripts );
$this->assertInstanceof( DOMNodeList::class, $other_scripts );
foreach ( $other_scripts as $script ) {
$this->assertInstanceof( Element::class, $script );
$this->assertSame( Tag::SCRIPT, $script->tagName );
$this->assertFalse( ValidationExemption::is_px_verified_for_node( $script ) );
}

// Inline Gtag events.
$inline_gtag_events = $dom->xpath->query( self::INLINE_GTAG_EVENT_XPATH );
$other_inline_events = $dom->xpath->query( '//@*[ substring(name(), 1, 2) = "on" and name() != "on" and not( contains(., "gtag(") ) ]' );

$this->assertCount( 2, $inline_gtag_events );
$this->assertInstanceof( DOMNodeList::class, $inline_gtag_events );
foreach ( $inline_gtag_events as $inline_gtag_event ) {
$this->assertInstanceof( DOMAttr::class, $inline_gtag_event );
$this->assertStringContainsString( 'on', $inline_gtag_event->nodeName );
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved
$this->assertEquals( $expect_px_verified, ValidationExemption::is_px_verified_for_node( $inline_gtag_event ) );
}

$this->assertCount( 2, $other_inline_events );
$this->assertInstanceof( DOMNodeList::class, $other_inline_events );
foreach ( $other_inline_events as $other_inline_event ) {
$this->assertInstanceof( DOMAttr::class, $other_inline_event );
$this->assertStringContainsString( 'on', $inline_gtag_event->nodeName );
thelovekesh marked this conversation as resolved.
Show resolved Hide resolved
$this->assertFalse( ValidationExemption::is_px_verified_for_node( $other_inline_event ) );
}
}
}