HTML — gtag.js snippet <!-- Google tag --> <script src="gtag/js?id=G-XXX" async></script> <script> gtag('config','G-XXX'); </script> GA4 Property page_view · events G-XXXXXXXXXX GA4 with gtag.js Direct Implementation Guide

Key takeaways

  • gtag.js is Google's universal tag — it handles GA4, Google Ads, and other Google products from a single snippet
  • Place the gtag.js snippet as high as possible in the <head> — before any other scripts that depend on it
  • The gtag('config') call sends an automatic page_view — disable it if you are managing page views manually
  • Custom events use gtag('event') with an event name and optional parameters — keep event names lowercase with underscores
  • Use GTM instead of direct gtag.js if you need flexibility to change tracking without code deployments

gtag.js is the direct installation method for GA4 — no tag manager, no intermediary layer, just a script tag in your HTML that connects your website to Google's data collection infrastructure. It is the fastest way to get GA4 running, and in certain situations it is the right choice. In most others, it is not.

This guide explains exactly how gtag.js works, what every line of the snippet does, how to send custom events, and how to make an informed decision about whether gtag.js or GTM is the right approach for your implementation.

What gtag.js actually is

gtag.js is a JavaScript library that provides a unified API for all Google measurement and advertising products. When you call gtag(), you are using a single function that can send data to GA4, Google Ads, Google Marketing Platform, and other Google services — all through the same snippet, configured with different product IDs.

It replaced the older analytics.js (Universal Analytics library) and is itself now the recommended direct-installation method. If you have an existing Universal Analytics implementation using analytics.js, that is a different, older library and needs to be replaced — not updated — for GA4.

Important distinction

gtag.js is not the same as Google Tag Manager. GTM is a tag management system that can load gtag.js (and many other tags) on your behalf. When people say "install GA4 via GTM", they mean GTM is loading and configuring gtag.js — not that GTM replaces it. The underlying library is the same either way.

The installation snippet — line by line

Here is the standard GA4 gtag.js snippet with every line explained:

HTML — GA4 gtag.js snippet annotated
<!-- Step 1: Load the gtag.js library asynchronously -->
<script async
  src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX">
</script>

<script>
  // Step 2: Initialise the dataLayer array if it doesn't exist
  window.dataLayer = window.dataLayer || [];

  // Step 3: Define the gtag function
  // Arguments object is used so all parameters are passed correctly
  function gtag(){ dataLayer.push(arguments); }

  // Step 4: Set the initial timestamp
  // Required — tells GA4 when the library was initialised
  gtag('js', new Date());

  // Step 5: Configure your GA4 property
  // This also sends an automatic page_view event
  gtag('config', 'G-XXXXXXXXXX');
</script>

A few things worth noting about this snippet:

  • The async attribute on the script tag means the library loads without blocking page rendering — this is correct and should always be present
  • The window.dataLayer = window.dataLayer || [] line initialises the dataLayer if it does not already exist — safe to have even if you are also using GTM
  • The gtag('js', new Date()) call is required — without it, GA4 cannot correctly attribute session timing
  • The gtag('config') call automatically fires a page_view event — you need to be aware of this if you are managing page views manually

Where to place the snippet

Place both script tags as high as possible in the <head> section of every page — immediately after the opening <head> tag, before any other scripts. This ensures:

  • GA4 starts initialising as early as possible in the page load
  • The page_view event is not delayed by other scripts
  • gtag is available to any other scripts on the page that might call it
HTML — correct placement in page template
<html>
<head>

  <!-- gtag.js goes FIRST, before other scripts -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){ dataLayer.push(arguments); }
    gtag('js', new Date());
    gtag('config', 'G-XXXXXXXXXX');
  </script>

  <!-- Other scripts and meta tags follow -->
  <meta charset="UTF-8">
  <title>Your Page Title</title>

</head>

Configuration options

The gtag('config') call accepts an optional third argument — a configuration object — that lets you customise GA4 behaviour:

JavaScript — gtag config options
gtag('config', 'G-XXXXXXXXXX', {

  // Disable automatic page_view on config load
  // Use this when you want to fire page_view manually
  send_page_view: false,

  // Override the page title sent to GA4
  page_title: 'Custom Page Title',

  // Override the page path
  page_path: '/custom/path',

  // Set cookie expiry in seconds (default: 63072000 = 2 years)
  cookie_expires: 63072000,

  // Restrict cookies to a specific domain
  cookie_domain: 'yourdomain.com',

  // Enable debug mode — sends events to DebugView
  debug_mode: true  // remove before production

});
Watch out

Setting send_page_view: false means GA4 will not record any page views unless you manually fire them using gtag('event', 'page_view'). This is useful for single-page applications where you control when page views are sent — but if you forget to fire the manual page view, you will have sessions with no page view events, which breaks session metrics.

Sending custom events

Custom events use the gtag('event') call with an event name and optional parameters:

JavaScript — custom event examples
// Basic custom event — no parameters
gtag('event', 'button_click');

// Custom event with parameters
gtag('event', 'form_submit', {
  form_name: 'contact_form',
  form_destination: 'sales_team'
});

// E-commerce purchase event
gtag('event', 'purchase', {
  transaction_id: 'T-12345',
  value: 4999,
  currency: 'INR',
  items: [{
    item_id: 'SKU-001',
    item_name: 'Product Name',
    price: 4999,
    quantity: 1
  }]
});

// Manual page_view (for SPAs)
gtag('event', 'page_view', {
  page_title: 'New Page Title',
  page_location: window.location.href
});

Event naming rules that matter for GA4 reporting:

  • Use lowercase letters, numbers, and underscores only
  • No spaces — use underscores instead (button_click not button click)
  • Maximum 40 characters for event names
  • Do not use reserved event names like click, download, scroll for custom events
  • Parameter names follow the same rules — lowercase with underscores, max 40 characters

Setting user properties

User properties persist across sessions and allow you to segment your reports by user characteristics. Set them using gtag('set'):

JavaScript — setting user properties
// Set user properties that persist across the session
gtag('set', 'user_properties', {
  membership_tier: 'premium',
  preferred_language: 'en',
  account_type: 'business'
});

// Set user ID for cross-device tracking
// Use a hashed or anonymised ID — never raw PII
gtag('config', 'G-XXXXXXXXXX', {
  user_id: 'hashed_user_id_here'
});
Privacy rule

Never pass real email addresses, phone numbers, names, or any personally identifiable information as user properties or event parameters. GA4's terms of service prohibit sending PII. Use hashed or anonymised identifiers only.

Using gtag.js with multiple Google products

One advantage of gtag.js over the older analytics.js is that a single snippet can configure multiple Google products. Add additional gtag('config') calls for each product:

JavaScript — multiple Google products from one snippet
gtag('js', new Date());

// GA4 property
gtag('config', 'G-XXXXXXXXXX');

// Google Ads conversion tracking
gtag('config', 'AW-XXXXXXXXXX');

// Floodlight (Campaign Manager)
gtag('config', 'DC-XXXXXXXXXX');

gtag.js vs GTM — when to use each

Situation Use gtag.js directly Use GTM
Simple site, GA4 only ✓ Simpler setup Overkill for basic needs
Need to add other tags later Requires code access each time ✓ Add tags without code changes
Custom event tracking Requires code changes per event ✓ Configure in GTM interface
Non-technical team managing tags Not suitable ✓ GTM interface accessible to non-devs
SPA / React / Next.js app ✓ Easier direct integration Needs extra configuration for SPAs
Multiple Google + third-party tags Gets complex quickly ✓ Centralised tag management
Speed of iteration on tracking Slow — needs dev deployment ✓ Fast — publish from GTM interface

The honest answer for most professional implementations: use GTM. The direct gtag.js approach makes sense for simple personal projects, prototypes, or React/Next.js applications where you are already managing state and want direct control over when events fire. For anything that needs to change over time, GTM is the right choice.

Debugging your implementation

Three ways to verify gtag.js is working DebugView Enable debug_mode: true OR use GA Debugger Chrome extension Best for event validation Network Tab DevTools → Network Filter: google-analytics Check /g/collect requests Best for request inspection GA4 Realtime Reports → Realtime See yourself as active user in last 30 min Best for quick confirmation
Fig 1. — Three debugging methods, each suited to a different verification need.

To enable debug mode temporarily for DebugView, add debug_mode: true to your config call. Remove it before going to production — debug events are sampled differently and can skew your data if left enabled.

JavaScript — enabling debug mode
// Add during testing, remove before production
gtag('config', 'G-XXXXXXXXXX', {
  debug_mode: true
});

The fastest way to confirm gtag.js is working correctly: open Chrome DevTools, go to the Network tab, filter by "collect", and reload the page. You should see a POST request to www.google-analytics.com/g/collect within the first second of page load. If you see that request, GA4 is receiving your data.

AB
Abhinav Bhargav
Founder, MetricByte Consulting · Adobe Certified Master — Analytics Architect

8 years implementing and auditing analytics programs across Adobe Analytics, AEP, GA4, and GTM for enterprise organizations. Founder of MetricByte Consulting. Connect on LinkedIn →