WordPress gtag.js with User ID tracking

I think you need to do a couple of things:

  • Move your calls to get the user inside your function – PHP variables aren’t shared across scopes without using global, which is generally a bad idea because it pollutes the global scope
  • Consolidate your JS
  • Use escaping methods before outputting data

With those in mind, I think this might work for you:

<?php
/**
 * Plugin Name: Analytics Suite
 * Plugin URI: -redacted-
 * Description: Implements Google Analytics using the new gtag.js and combining user id.
 * Author: -redacted-
 * Version: 1.0
 */
function ns_google_analytics() {
    $user = wp_get_current_user();
?>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX"></script>
    <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
<?php if ( 0 !== $user->ID ) : ?>
    gtag('config', 'UA-XXXXXXX', {
        'user_id': '<?php echo esc_js( $user->user_login ); ?>'
    });
<?php else : ?>
    gtag('config', 'UA-XXXXXXX');
<?php endif; ?>
    </script>
 <?php
 }
add_action( 'wp_head', 'ns_google_analytics', 10 );

In the above code:

  • We get the user outright using wp_get_current_user. From the WordPress codex (Emphasis mine):

    WP_User object where it can be retrieved using member variables. Attribute ID will show 0 if there is no user.

  • This means you will always get a \WP_User back, and you can check if the ID is zero to determine if a user is logged in or not.
  • Your conditional if statement really only needs to output specific JS in one spot, so those areas are consolidated
  • All output should be escaped, hence the use of esc_js