diff --git a/includes/sanitizers/class-amp-img-sanitizer.php b/includes/sanitizers/class-amp-img-sanitizer.php
index 77666faa747..9188ac2f05e 100644
--- a/includes/sanitizers/class-amp-img-sanitizer.php
+++ b/includes/sanitizers/class-amp-img-sanitizer.php
@@ -183,6 +183,26 @@ public function sanitize() {
continue;
}
+ // Replace img with amp-pixel when dealing with tracking pixels.
+ if ( self::is_tracking_pixel_url( $node->getAttribute( Attribute::SRC ) ) ) {
+ $attributes = [
+ Attribute::SRC => $node->getAttribute( Attribute::SRC ),
+ Attribute::LAYOUT => Layout::NODISPLAY,
+ ];
+ foreach ( [ Attribute::REFERRERPOLICY ] as $allowed_attribute ) {
+ if ( $node->hasAttribute( $allowed_attribute ) ) {
+ $attributes[ $allowed_attribute ] = $node->getAttribute( $allowed_attribute );
+ }
+ }
+ $amp_pixel_node = AMP_DOM_Utils::create_node(
+ $this->dom,
+ Extension::PIXEL,
+ $attributes
+ );
+ $node->parentNode->replaceChild( $amp_pixel_node, $node );
+ continue;
+ }
+
// Short-circuit emoji images from needing to make requests out to https://s.w.org/.
if ( 'wp-smiley' === $node->getAttribute( Attribute::CLASS_ ) ) {
$node->setAttribute( Attribute::WIDTH, '72' );
@@ -552,4 +572,27 @@ private function is_gif_url( $url ) {
$path = wp_parse_url( $url, PHP_URL_PATH );
return substr( $path, -strlen( $ext ) ) === $ext;
}
+
+ /**
+ * Determines if a URL is a known tracking pixel URL.
+ *
+ * Currently, only Facebook tracking pixel URL is detected.
+ *
+ * @since 2.2.2
+ *
+ * @param string $url URL to inspect.
+ *
+ * @return bool Returns true if $url is a tracking pixel URL.
+ */
+ private static function is_tracking_pixel_url( $url ) {
+ $parsed_url = wp_parse_url( $url );
+
+ return (
+ isset( $parsed_url['host'], $parsed_url['path'] )
+ &&
+ 'facebook.com' === str_replace( 'www.', '', $parsed_url['host'] )
+ &&
+ '/tr' === $parsed_url['path']
+ );
+ }
}
diff --git a/tests/php/test-amp-img-sanitizer.php b/tests/php/test-amp-img-sanitizer.php
index c2d083ac4b2..9742e32fbfb 100644
--- a/tests/php/test-amp-img-sanitizer.php
+++ b/tests/php/test-amp-img-sanitizer.php
@@ -575,6 +575,16 @@ public function get_data() {
AMP_Tag_And_Attribute_Sanitizer::WRONG_PARENT_TAG,
],
],
+
+ 'facebook_pixel_img_to_amp_pixel' => [
+ '
',
+ '',
+ ],
+
+ 'facebook_pixel_img_to_amp_pixel_with_referrer' => [
+ '
',
+ '',
+ ],
];
}
@@ -923,4 +933,48 @@ public function test_process_picture_elements( $input, $args, $expected ) {
$this->assertEqualMarkup( $expected, $actual, "Actual content:\n$actual" );
}
+
+ /**
+ * @return array
+ */
+ public function get_data_for_test_is_tracking_pixel_url() {
+ return [
+ 'facebook_pixel_url_no_ssl_no_www' => [
+ 'url' => 'http://facebook.com/tr?id=123456789012345',
+ 'expected' => true,
+ ],
+ 'facebook_pixel_url_no_ssl_www' => [
+ 'url' => 'http://www.facebook.com/tr?id=123456789012345',
+ 'expected' => true,
+ ],
+ 'facebook_pixel_url_ssl_no_www' => [
+ 'url' => 'https://facebook.com/tr?id=123456789012345',
+ 'expected' => true,
+ ],
+ 'facebook_pixel_url_ssl_www' => [
+ 'url' => 'https://www.facebook.com/tr?id=123456789012345',
+ 'expected' => true,
+ ],
+ 'facebook_page_url' => [
+ 'url' => 'https://www.facebook.com/traffic?id=123456789012345',
+ 'expected' => false,
+ ],
+ 'relative_url' => [
+ 'url' => '/tr?id=123456789012345',
+ 'expected' => false,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider get_data_for_test_is_tracking_pixel_url()
+ *
+ * @covers ::is_tracking_pixel_url()
+ */
+ public function test_is_tracking_pixel_url( $url, $expected ) {
+ $this->assertEquals(
+ $expected,
+ $this->call_private_static_method( AMP_Img_Sanitizer::class, 'is_tracking_pixel_url', [ $url ] )
+ );
+ }
}