User ID Tracking Implementation Issues | Blue Frog Docs

User ID Tracking Implementation Issues

Diagnose and fix User ID tracking problems that prevent accurate cross-device and logged-in user analysis

User ID Tracking Implementation Issues

What This Means

User ID tracking allows analytics platforms to track the same user across multiple devices, sessions, and browsers by assigning a persistent identifier to logged-in users. Without proper User ID implementation, you can't accurately track cross-device journeys, customer lifetime value, or behavior of authenticated users.

Common User ID Problems

Not Implemented:

  • No User ID sent to analytics
  • Only using client ID (device-based)
  • Missing for logged-in users
  • Not configured in analytics property

Implementation Errors:

  • User ID sent before consent
  • PII (email, name) used as User ID
  • User ID not persistent across sessions
  • Not sent on all relevant hits
  • Inconsistent ID format

Technical Issues:

  • User ID cleared on logout not handled
  • Race conditions on page load
  • SPA navigation missing User ID
  • Server-side vs client-side mismatch

Impact on Your Business

Analytics Accuracy:

  • Can't track cross-device journeys
  • Inflated user counts (same user = multiple users)
  • Inaccurate customer lifetime value
  • Can't analyze logged-in user behavior properly
  • Lost attribution for converting users

Business Intelligence:

  • Poor understanding of customer journey
  • Can't identify high-value users
  • Difficult to optimize for logged-in experience
  • Incomplete funnel analysis
  • Lost marketing attribution

Personalization:

  • Can't create audiences of logged-in users
  • Difficult to retarget authenticated users
  • Missing cross-device remarketing opportunities

Privacy & Compliance:

  • Using PII as User ID = GDPR violation
  • Tracking without consent = legal liability
  • Data subject access requests incomplete

How to Diagnose

Method 1: Google Analytics 4 DebugView

  1. Enable debug mode:

    gtag('config', 'G-XXXXXXXXXX', {
      'debug_mode': true
    });
    
  2. Open Google Analytics

  3. Go to Admin → DebugView

  4. Navigate your site while logged in

  5. Check events for user_id parameter

What to Look For:

  • user_id present on events
  • Value is NOT email or name
  • Consistent across events
  • Present after login
  • Cleared after logout

Method 2: Browser Developer Tools (Network Tab)

  1. Open DevTools (F12)
  2. Navigate to "Network" tab
  3. Filter by "analytics" or "collect"
  4. Log in to your site
  5. Check requests for User ID parameter

Google Analytics 4:

Look for: &uid=12345

Google Analytics Universal:

Look for: &uid=user123

What to Look For:

  • User ID parameter present after login
  • Not present before login
  • Consistent format
  • Not containing PII

Method 3: Google Tag Manager Preview Mode

  1. Open Google Tag Manager
  2. Click "Preview"
  3. Navigate to your site
  4. Log in
  5. Check variables and data layer

What to Look For:

  • User ID variable populated after login
  • Available in data layer
  • Sent with all relevant tags
  • Correct format

Method 4: Check Analytics Reports

Google Analytics 4:

  1. Navigate to Reports
  2. Explore → User Explorer
  3. Filter by logged-in users
  4. Check if User ID is being used

Google Analytics Universal:

  1. Navigate to User Explorer
  2. Check Client ID vs User ID views
  3. Verify cross-device reports available

What to Look For:

  • User ID view shows data
  • Lower user count in User ID view (expected)
  • Cross-device reports populated

Method 5: Test Cross-Device Tracking

  1. Log in on desktop browser
  2. Perform an action (e.g., add to cart)
  3. Log in on mobile device with same account
  4. Perform another action
  5. Check analytics for unified session

What to Look For:

  • Single user shown in analytics
  • Actions from both devices attributed correctly
  • Journey properly connected

General Fixes

Fix 1: Implement User ID Properly in GA4

Basic implementation:

// When user logs in
function onUserLogin(userId) {
  // Send User ID to Google Analytics 4
  gtag('config', 'G-XXXXXXXXXX', {
    'user_id': userId // Use internal user ID, NOT email
  });

  // Optional: Set as user property
  gtag('set', 'user_properties', {
    'user_id': userId
  });
}

// When user logs out
function onUserLogout() {
  // Clear User ID
  gtag('config', 'G-XXXXXXXXXX', {
    'user_id': null
  });
}

With consent management:

function onUserLogin(userId, hasConsent) {
  if (!hasConsent) {
    console.warn('User has not consented to analytics');
    return;
  }

  gtag('config', 'G-XXXXXXXXXX', {
    'user_id': userId
  });
}

Fix 2: Implement User ID in Universal Analytics

Using gtag.js:

// Set User ID when known
gtag('config', 'UA-XXXXXXXXX-X', {
  'user_id': 'USER_ID'
});

// Send user_id with events
gtag('event', 'login', {
  'method': 'email',
  'user_id': 'USER_ID'
});

Using analytics.js:

// Set User ID
ga('create', 'UA-XXXXXXXXX-X', {
  'userId': 'USER_ID'
});

// Or set later
ga('set', 'userId', 'USER_ID');

Fix 3: Implement via Google Tag Manager

Create User ID Variable:

  1. GTM → Variables → New
  2. Variable Type: Data Layer Variable
  3. Data Layer Variable Name: userId
  4. Save as "User ID"

Update GA4 Configuration Tag:

  1. Edit GA4 Configuration tag
  2. Fields to Set
  3. Add field: user_id = \{\{User ID\}\}
  4. Save and publish

Push to Data Layer on Login:

// When user logs in
function onLoginSuccess(userId) {
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'event': 'login',
    'userId': userId,
    'userStatus': 'logged_in'
  });
}

// When user logs out
function onLogoutSuccess() {
  window.dataLayer.push({
    'event': 'logout',
    'userId': undefined,
    'userStatus': 'logged_out'
  });
}

Fix 4: Generate Proper User IDs

Best practices for User ID:

// Good: Internal database ID
const userId = user.id; // e.g., "12345"

// Good: Hashed email (if needed)
const userId = await hashEmail(user.email);

async function hashEmail(email) {
  const msgBuffer = new TextEncoder().encode(email);
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Bad: Email address (PII violation)
const userId = user.email; // ❌ Don't do this

// Bad: Name (PII violation)
const userId = user.fullName; // ❌ Don't do this

// Bad: Combines PII
const userId = `${user.email}_${user.name}`; // ❌ Don't do this

Format requirements:

  • Cannot contain PII
  • Must be persistent
  • Should be consistent across platforms
  • Alphanumeric recommended
  • Max 256 characters

Fix 5: Handle User ID in Single Page Applications

React example:

import { useEffect } from 'react';
import { useAuth } from './auth-context';

function App() {
  const { user, isAuthenticated } = useAuth();

  useEffect(() => {
    if (isAuthenticated && user?.id) {
      // Set User ID
      gtag('config', 'G-XXXXXXXXXX', {
        'user_id': user.id
      });

      // Set user properties
      gtag('set', 'user_properties', {
        'account_type': user.accountType,
        'member_since': user.createdAt
      });
    } else {
      // Clear User ID
      gtag('config', 'G-XXXXXXXXXX', {
        'user_id': null
      });
    }
  }, [isAuthenticated, user]);

  return <div>{/* App content */}</div>;
}

Vue example:

import { watch } from 'vue';
import { useAuth } from '@/composables/auth';

export default {
  setup() {
    const { user, isAuthenticated } = useAuth();

    watch([isAuthenticated, user], ([authenticated, currentUser]) => {
      if (authenticated && currentUser?.id) {
        gtag('config', 'G-XXXXXXXXXX', {
          'user_id': currentUser.id
        });
      } else {
        gtag('config', 'G-XXXXXXXXXX', {
          'user_id': null
        });
      }
    });
  }
};

Fix 6: Implement Server-Side User ID

Next.js example:

// pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';

function MyApp({ Component, pageProps }) {
  const { data: session } = useSession();
  const router = useRouter();

  useEffect(() => {
    // Set User ID when session available
    if (session?.user?.id) {
      gtag('config', process.env.NEXT_PUBLIC_GA_ID, {
        'user_id': session.user.id
      });
    }
  }, [session]);

  useEffect(() => {
    // Track page views with User ID
    const handleRouteChange = (url) => {
      gtag('config', process.env.NEXT_PUBLIC_GA_ID, {
        'page_path': url,
        'user_id': session?.user?.id || null
      });
    };

    router.events.on('routeChangeComplete', handleRouteChange);
    return () => {
      router.events.off('routeChangeComplete', handleRouteChange);
    };
  }, [router.events, session]);

  return <Component {...pageProps} />;
}

Fix 7: Configure User ID View in Analytics

Google Analytics 4:

  1. Admin → Data Settings → Data Collection
  2. Enable "User-ID"
  3. User ID already works automatically when sent

Google Analytics Universal:

  1. Admin → Property → Tracking Info → User-ID
  2. Create User-ID view
  3. Configure settings:
    • Enable User-ID reporting
    • Bot filtering: ON
    • Enhanced Link Attribution: ON

Platform-Specific Guides

Detailed implementation instructions for your specific platform:

Platform Troubleshooting Guide
Shopify Shopify User ID Tracking Guide
WordPress WordPress User ID Tracking Guide
Wix Wix User ID Tracking Guide
Squarespace Squarespace User ID Tracking Guide
Webflow Webflow User ID Tracking Guide

Verification

After implementing User ID tracking:

  1. Debug mode testing:

    • Enable GA4 debug mode
    • Log in to your site
    • Check DebugView for user_id
    • Verify on all events
  2. Network tab verification:

    • Check analytics requests
    • Confirm user_id parameter present
    • Verify not sending PII
  3. Cross-device testing:

    • Log in on desktop
    • Log in on mobile with same account
    • Check analytics for unified user
  4. Analytics reports:

    • Wait 24-48 hours
    • Check User Explorer
    • Verify User ID view has data
    • Compare with Client ID view
  5. Privacy compliance:

    • User ID is not PII
    • Only sent with consent
    • Cleared on logout
    • Documented in privacy policy

Common Mistakes

  1. Using email as User ID - GDPR/privacy violation
  2. Not clearing on logout - Data persists incorrectly
  3. Sending before consent - Privacy violation
  4. Not configuring User ID view - Can't see the data (UA)
  5. Only on some events - Inconsistent tracking
  6. Not handling SPA navigation - Lost on route changes
  7. Using unstable IDs - Changes between sessions
  8. Not testing cross-device - May not work as expected
  9. Forgetting server-side - Only implementing client-side
  10. No error handling - Fails silently

Additional Resources

// SYS.FOOTER