EnrichmentAvailable now

    Device data, already parsed.

    The User-Agent string arrives on every request, but turning it into something usable means shipping and maintaining a parser inside your container. This module does the parsing at the gateway and hands your tags three clean headers instead.

    Three ready-to-use headers
    No parser to maintain
    Bounded, predictable values
    All modules
    User-Agent header
    Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
    Parsed at the gateway
    Headers your tags receive
    X-Device-Categorydesktop
    X-Device-OSmacOS
    X-Device-BrowserChrome

    Values are family-level on purpose: bounded cardinality keeps tag logic simple and reporting dimensions cheap.

    One string in, three fields out

    Parsing user agents is a maintenance problem, not a feature

    Every server-side setup eventually needs device context. Getting there normally means writing regular expressions inside a tag template and then keeping them current forever.

    01

    The string is not designed to be read

    Modern user agents are a pile of compatibility tokens. Every browser claims to be Mozilla, and most claim to be Safari as well.

    02

    Custom parsers rot

    A regular expression written today misclassifies next year's browser release. Nobody notices until a report looks strange months later.

    03

    Cardinality gets out of hand

    Feeding raw strings into reporting produces thousands of near-identical values, which is expensive to store and useless to segment on.

    How it works

    The gateway classifies the User-Agent on each request and appends three headers. Your tags read them with the standard Request Header variable, no template, no code.

    01

    Category

    X-Device-Category resolves to desktop, mobile, tablet or bot: the split most reporting and bidding decisions actually turn on.

    02

    Operating system

    X-Device-OS resolves to Windows, Android, iOS, ChromeOS, macOS or Linux.

    03

    Browser

    X-Device-Browser resolves to Chrome, Safari, Firefox, Edge, Opera or Samsung Internet.

    04

    Empty rather than wrong

    When the User-Agent is missing or unrecognised, the header is empty. A blank value is easy to filter; a guessed one quietly corrupts a segment.

    What you get

    Family-level by design

    Values are deliberately coarse. Bounded cardinality keeps tag logic simple and reporting dimensions cheap.

    Bot classification included

    Recognised crawlers are categorised as bot, so you can exclude them from conversions before they distort a campaign.

    Nothing to configure

    There are no settings. The header set is the product: enable it and the headers arrive.

    Consistent with our analytics

    The same classification granularity is used across the platform, so device splits agree wherever you look at them.

    Specification

    X-Device-Category
    desktop | mobile | tablet | bot
    X-Device-OS
    Windows | Android | iOS | ChromeOS | macOS | Linux
    X-Device-Browser
    Chrome | Safari | Firefox | Edge | Opera | Samsung Internet
    Settings
    None, the header set is fixed
    Cost
    Included with your container
    Request headers
    X-Device-CategoryX-Device-OSX-Device-Browser

    When to use it

    You want device dimensions server-side

    Send device category to GA4, Meta or your warehouse without a client-side variable that a blocker can prevent from ever running.

    You route tags conditionally

    Trigger app-install tags only for mobile, or suppress a vendor entirely for bot traffic, using a header rather than a fragile string comparison.

    You are cleaning up bot traffic

    Filtering on a single categorised header is far more reliable than maintaining a crawler regular expression inside a tag.

    Questions about User Agent Info

    How do I read these in server-side GTM?

    Create a Request Header variable and enter the header name, for example X-Device-Category. It is available to every tag in the container from that point on.

    Why not more detailed values, like exact versions?

    Version-level detail explodes cardinality and is rarely what a decision turns on. Family-level values stay stable across releases and keep your tag logic readable.

    Does it work with Client Hints?

    The module reads the User-Agent header, which browsers continue to send. Where Client Hints are present they do not conflict; you simply have both available.

    Other modules

    Modules stack. Enable as many as you need. They compose into one configuration in front of your container.

    Ready to switch it on?

    Every module is included with your container at no extra cost. Create a container, open the modules panel, and toggle.

    See pricing