5 min read

What Is Data Streams in Google Analytics 4

Data Streams are the connection points between your website, app, or server and Google Analytics 4. Without them, GA4 has no way to route your data to the right property or apply stream-specific processing. Each stream gets a Measurement ID—that's the identifier you paste into your code to start tracking.

Understanding Data Streams

A Data Stream is a logical path for data from a single source into your GA4 property. Every source you track needs its own stream.

Know what a Data Stream actually is

Think of a Data Stream as a labeled container and configuration bundle. It represents one tracking source—your website, iOS app, Android app, or server. GA4 uses the Measurement ID from the stream to identify which property and which stream receives the incoming data. The stream also holds its own settings, filters, and processing rules that apply only to that source.

javascript
// Your Measurement ID identifies the Data Stream
// Format: G-XXXXXXXXXX
// This code sends data to the stream with ID G-ABC123DEF456
<script async src="https://www.googletagmanager.com/gtag/js?id=G-ABC123DEF456"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-ABC123DEF456');
</script>
The Measurement ID in your gtag.js code routes data to a specific Data Stream

Recognize when to create separate streams

Create a new Data Stream for each distinct source you want to track independently. Common setup: one stream for your website, another for your iOS app, another for Android. You can also create separate streams for production vs. staging environments. Each stream generates its own Measurement ID, and you use conditional logic in your code to load the right one.

javascript
// Load the correct Measurement ID based on environment
const measurementId = process.env.NODE_ENV === 'production'
  ? 'G-PROD_ABC123'    // Production website data stream
  : 'G-DEV_ABC123';     // Development/staging data stream

gtag('config', measurementId, {
  'page_path': window.location.pathname
});
Use environment variables to route data to the correct stream
Watch out: Using the same Measurement ID across production and test environments means test events get counted as real user data. Always create a separate Data Stream for dev/staging.

Creating and Configuring Data Streams

You set up Data Streams once in the GA4 UI, then reference the Measurement ID everywhere you track from that source.

Locate your Data Streams in GA4

In your GA4 property, go to Admin > Data Streams. This page lists every stream connected to your property. Click on any stream to see its Measurement ID, platform (Web, iOS, Android), stream name, and creation date. This is where you also create new streams.

javascript
// Programmatically fetch your data streams using the Admin API
const analytics = require('@google-analytics/admin');

const client = new analytics.AnalyticsAdminServiceClient();
const streams = await client.listDataStreams({
  parent: `properties/${propertyId}`
});

streams.forEach(stream => {
  console.log(`Stream: ${stream.displayName}, ID: ${stream.name}`);
});
Use the Admin API to list all Data Streams in your property

Create a new Data Stream

Click Create stream in the Data Streams page. Select your platform (Web, iOS, or Android), give it a descriptive name (e.g., "Website - Production" or "iOS App - Staging"), and complete the platform-specific setup. GA4 generates a Measurement ID (format: G-XXXXXXXXXX). Copy this ID—you'll use it to initialize analytics on your source.

javascript
// After creating your stream, initialize gtag.js with your new Measurement ID
<script async src="https://www.googletagmanager.com/gtag/js?id=G-YOUR_NEW_ID"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-YOUR_NEW_ID', {
    'page_title': document.title,
    'page_location': window.location.href
  });
</script>
Paste your Measurement ID from the new stream into your website code

Configure stream-level settings

In the Stream details tab, you can enable Enhanced measurement (automatically captures scrolls, outbound clicks, form submissions), set your domain list, adjust session timeout (default 30 minutes), and manage other stream-specific configurations. These settings apply only to this stream, not to other streams in the same property.

javascript
// Customize stream behavior with gtag.js config parameters
gtag('config', 'G-MEASUREMENT_ID', {
  'page_path': window.location.pathname,
  'page_title': document.title,
  'anonymize_ip': true,
  'cookie_domain': 'auto',
  'session_duration_milliseconds': 1800000  // 30 minutes
});
Configure stream options directly from your tracking code
Tip: Use clear, descriptive stream names like "Website Production" or "Mobile App Beta" so you instantly know which source each stream represents. Avoid vague names like "Stream 1".

Why Data Streams Matter for Your Analytics

Data Streams organize your data at the source level and let you apply stream-specific logic without creating separate GA4 properties.

Apply stream-level data processing

Each Data Stream has its own Data Filters and Event Filters in the admin. You can exclude internal traffic, filter out bot activity, or remove test events—but only for that specific stream. Production and staging streams are unaffected. This keeps your production analytics clean without having to delete data.

javascript
// Filter traffic client-side before sending to GA4 to reduce quota usage
const isInternalUser = isInternalIP(clientIP) || userEmail.includes('@company.com');

if (!isInternalUser) {
  gtag('event', 'page_view', {
    'page_path': window.location.pathname,
    'page_title': document.title
  });
}
Conditionally send events to prevent internal traffic from reaching GA4

Separate reporting by source

Because each source has its own Measurement ID and Data Stream, you can see web traffic separately from app traffic in your reports. You can also create stream-level segments to isolate data from a specific stream. This clarity makes it easier to diagnose issues—if your app stream shows no events, you know to check your mobile implementation, not your website.

javascript
// Track a custom event from your website stream
gtag('event', 'product_added', {
  'value': 99.99,
  'currency': 'USD',
  'source': 'web'  // Helps identify this came from the web stream
});

// A separate mobile app uses a different Measurement ID
// and sends the same event with source: 'app'
Use custom dimensions to tag events with their source
Watch out: Stream-level filters are applied to incoming data, not retroactively to historical data. If you enable a filter, past events remain unfiltered.

Common Pitfalls

  • Using the same Measurement ID in production and development—test events get counted as real traffic
  • Creating too many streams when one would suffice, making reporting fragmented and harder to analyze overall performance
  • Forgetting which Measurement ID belongs to which stream, leading to data sent to the wrong stream
  • Assuming stream filters apply to historical data—they only affect events received after the filter is enabled

Wrapping Up

Data Streams are how GA4 organizes data by source. Each website, app, or server tracking source needs its own stream and Measurement ID. Set them up correctly at the start, use the right ID in your code, and keep production separate from testing. If you want to track this automatically across tools, Product Analyst can help.

Track these metrics automatically

Product Analyst connects to your stack and surfaces the insights that matter.

Try Product Analyst — Free