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

Google Analytics Tracking Code Placed Incorrectly #9129

Closed
joendotcom opened this issue Mar 22, 2018 · 12 comments · Fixed by #17184
Closed

Google Analytics Tracking Code Placed Incorrectly #9129

joendotcom opened this issue Mar 22, 2018 · 12 comments · Fixed by #17184
Assignees
Labels
Customer Report Issues or PRs that were reported via Happiness. aka "Happiness Request", or "User Report" [Feature] Google Analytics [Pri] Low [Type] Bug When a feature is broken and / or not performing as intended

Comments

@joendotcom
Copy link

joendotcom commented Mar 22, 2018

Summary

User reports that this issue causes trouble with Google Analytics tracking.

Referenced in 1036031-zen.

Steps to reproduce the issue

  1. Starting from a test site with Google Analytics tracking: https://joentest1.mystagingwebsite.com/
  2. View page source
  3. Search for <!-- Jetpack Google Analytics -->

What I expected

Google Analytics tracking code is shown as outlined in this article:

right after the <head> tag on each page of your site.

What happened instead

Google Analytics code is not inside <head> and instead appears on line 328 (on the test site).

screen shot 2018-03-22 at 21 39 07

@georgestephanis
Copy link
Member

georgestephanis commented Mar 22, 2018

The code on or about line 328 (bottom of the <body> tag) is:

<!-- Jetpack Google Analytics -->
			<script type='text/javascript'>
				var _gaq = _gaq || [];
				_gaq.push(['_setAccount', 'UA-123456789-1']);
_gaq.push(['_trackPageview']);
				(function() {
					var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
					ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
					var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
				})();
			</script>

which doesn't line up with the output of the Jetpack_Google_Analytics_Universal::wp_head() method --

public function wp_head() {
$tracking_code = Jetpack_Google_Analytics_Options::get_tracking_code();
if ( empty( $tracking_code ) ) {
echo "<!-- No tracking ID configured for Jetpack Google Analytics -->\r\n";
return;
}
// If we're in the admin_area, return without inserting code.
if ( is_admin() ) {
return;
}
// At this time, we only leverage universal analytics for enhanced ecommerce. If WooCommerce is not
// present, don't bother emitting the tracking ID or fetching analytics.js
if ( ! class_exists( 'WooCommerce' ) ) {
return;
}
/**
* Allow for additional elements to be added to the universal Google Analytics queue (ga) array
*
* @since 5.6.0
*
* @param array $custom_vars Array of universal Google Analytics queue elements
*/
$universal_commands = apply_filters( 'jetpack_wga_universal_commands', array() );
$async_code = "
<!-- Jetpack Google Analytics -->
<script>
window.ga = window.ga || function(){ ( ga.q = ga.q || [] ).push( arguments ) }; ga.l=+new Date;
ga( 'create', '%tracking_id%', 'auto' );
ga( 'require', 'ec' );
%universal_commands%
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Jetpack Google Analytics -->
";
$async_code = str_replace( '%tracking_id%', $tracking_code, $async_code );
$universal_commands_string = implode( "\r\n", $universal_commands );
$async_code = str_replace( '%universal_commands%', $universal_commands_string, $async_code );
echo "$async_code\r\n";
}

but does match the Jetpack_Google_Analytics_Legacy::insert_code() method:

/**
* This injects the Google Analytics code into the footer of the page.
* Called exclusively by wp_footer action
*/
public function insert_code() {
$tracking_id = Jetpack_Google_Analytics_Options::get_tracking_code();
if ( empty( $tracking_id ) ) {
echo "<!-- Your Google Analytics Plugin is missing the tracking ID -->\r\n";
return;
}
// If we're in the admin_area, return without inserting code.
if ( is_admin() ) {
return;
}
$custom_vars = array(
"_gaq.push(['_setAccount', '{$tracking_id}']);",
);
$track = array();
if ( is_404() ) {
// This is a 404 and we are supposed to track them.
$custom_vars[] = "_gaq.push(['_trackEvent', '404', document.location.href, document.referrer]);";
} elseif ( is_search() ) {
// Set track for searches, if it's a search, and we are supposed to.
$track['data'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // Input var okay.
$track['code'] = 'search';
}
if ( ! empty( $track ) ) {
$track['url'] = $this->_get_url( $track );
// adjust the code that we output, account for both types of tracking.
$track['url'] = esc_js( str_replace( '&', '&amp;', $track['url'] ) );
$custom_vars[] = "_gaq.push(['_trackPageview','{$track['url']}']);";
} else {
$custom_vars[] = "_gaq.push(['_trackPageview']);";
}
/**
* Allow for additional elements to be added to the classic Google Analytics queue (_gaq) array
*
* @since 5.4.0
*
* @param array $custom_vars Array of classic Google Analytics queue elements
*/
$custom_vars = apply_filters( 'jetpack_wga_classic_custom_vars', $custom_vars );
// Ref: https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingEcommerce#Example
printf(
"<!-- Jetpack Google Analytics -->
<script type='text/javascript'>
var _gaq = _gaq || [];
%s
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>\r\n",
implode( "\r\n", $custom_vars )
);
}

which is run in the footer --

add_action( 'wp_footer', array( $this, 'insert_code' ) );

The legacy is run instead of the universal code, as evaluates to false:

if ( Jetpack_Google_Analytics_Options::enhanced_ecommerce_tracking_is_enabled() ) {
$analytics = new Jetpack_Google_Analytics_Universal();
} else {
$analytics = new Jetpack_Google_Analytics_Legacy();
}

// Enhanced eCommerce options
public static function enhanced_ecommerce_tracking_is_enabled() {
return self::get_option( 'enh_ec_tracking' );
}

which came from #8182 by @allendav to add support for the newer universal analytics js.

The linked article in the original issue is for gtag.js tracking, which I think is yet another form of google analytics that we may not be explicitly supporting? I'm unsure, but would defer to @allendav on that.

@rtrevellyan
Copy link

As far as I know, gtag.js is simply the 'latest and greatest' version of the tracking code.

@designsimply designsimply added the [Type] Bug When a feature is broken and / or not performing as intended label Mar 22, 2018
@georgestephanis
Copy link
Member

Looks like gtag is inclusive of a number of other google stuff as well, such as Google Tag Manager --

https://www.lunametrics.com/blog/2017/12/12/what-is-gtag-google-analytics/

As such, it may be a "do not ever ever ever run on WordPress.com sites" tag as it can allow the inclusion of arbitrary Javascript and lead to XSS attacks on user accounts from malicious wp.com subdomains running nasty custom js that we ordinarily would block.

@rtrevellyan
Copy link

My desire is to have the GA code inserted in the head, not necessarily to have the use of gtag. When the GA code is not in the head, Search Console will not validate the domain. While there are other ways to validate a domain, when one is already using GA, it makes sense to also validate with GA. I only recently discovered that this was an issue when Search Console tried to automatically revalidate a couple of dozen of domains that we manage and they all failed because I had switched them to Jetpack's GA module (away from the GA Google Analytics plugin).

I believe there may be other issues with GA code not being in the head. I encountered an error message (which I failed to save - doh!) that seemed to be telling me that, because the GA code ran after another code, it failed to recognize the page view and thus could not record its results properly.

@georgestephanis
Copy link
Member

@allendav Would it be bad to have non-eCommerce ways to switch a site to using the universal tag?

https://github.com/Automattic/wp-calypso/blob/48e65376175054f54659ce50b2316b3e60b37a37/client/my-sites/site-settings/form-analytics-stores.jsx#L97-L105

I suppose we could also just do something like

add_filter( 'option_jetpack_wga', 'force_jetpack_ga_to_universal' );
function force_jetpack_ga_to_universal( $value ) {
    if ( is_array( $value ) ) {
        $value['enh_ec_tracking'] = true;
    }
    return $value;
} );

@rtrevellyan
Copy link

I see @jeherve marked this low priority. Of course, I don't know how you determine bug priority, but I just want to reiterate that this issue makes Jetpack's GA module useless to me.

@allendav
Copy link
Contributor

@georgestephanis wrote

Would it be bad to have non-eCommerce ways to switch a site to using the universal tag?

It would not be bad. Besides a filter like yours, we also have to allow analytics.js to be added when WooCommerce isn't present. I am also trying to remember why I set the priority for wp_head for Jetpack_Google_Analytics_Universal so high (as @rtrevellyan noted it should be near the top, not near the bottom of the head ). Will have a patch shortly to allow for all this. Sorry for the delay.

cc @rtrevellyan

@allendav
Copy link
Contributor

@georgestephanis @rtrevellyan @joendotcom - feedback welcome - #9333

@rtrevellyan
Copy link

I'm puzzled by the choice being between ga.js and analytics.js, instead of between analytics.js and gtag.js. If there's a need to support the legacy ga.js, perhaps that's the version that should be enabled by a filter.

ga.js is a legacy library. If you are starting a new implementation, we recommend you use the latest version of this library, analytics.js. For existing implementations, learn how to migrate from ga.js to analytics.js.

from https://developers.google.com/analytics/devguides/collection/gajs/

@allendav
Copy link
Contributor

allendav commented Apr 17, 2018

Hi @rtrevellyan - the jetpack module used to be ga.js only, and then in Jetpack 5.6 I was asked to port the analytics.js code for eCommerce from another one of our plugins to Jetpack. At the time, I wasn't even aware of gtag.js's existence.

Perhaps a future version of this module will add gtag.js support and/or support enabling analytics.js without the filter - please feel free to create such issues if you'd like.

@stale
Copy link

stale bot commented Oct 14, 2018

This issue has been marked as stale. This happened because:

  • It has been inactive in the past 6 months.
  • It hasn’t been labeled `[Pri] Blocker`, `[Pri] High`.

No further action is needed. But it's worth checking if this ticket has clear reproduction steps and it is still reproducible. Feel free to close this issue if you think it's not valid anymore — if you do, please add a brief explanation.

@stale stale bot added the [Status] Stale label Oct 14, 2018
@matticbot matticbot added the Customer Report Issues or PRs that were reported via Happiness. aka "Happiness Request", or "User Report" label Sep 16, 2020
@simison
Copy link
Member

simison commented Sep 16, 2020

Still an issue.

With https://search.google.com/search-console:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Customer Report Issues or PRs that were reported via Happiness. aka "Happiness Request", or "User Report" [Feature] Google Analytics [Pri] Low [Type] Bug When a feature is broken and / or not performing as intended
Projects
None yet
9 participants