DEV Community

Ruben Cali
Ruben Cali

Posted on

What Server-Side GTM Really Costs a 20k-Visit WordPress Site

"You need a server-side container. Everyone's moving to it."

That was the whole recommendation. A client had come to us with a report that made no sense.
One channel had been cut from the media plan for underperforming, the client's own sales
inbox disagreed, and the answer they had already been given by a consultant was a
GTM server container, which is one alternative among several and not automatically the right
one at their size. Nobody had priced it. Nobody had asked who would maintain it after launch.

The recommendation is not wrong. It is just frequently unpriced, and the price is where the
decision actually lives. Here is the breakdown we did, and the line where it flips.

What sGTM is

Server-side Google Tag Manager moves tag execution off the browser. Instead of the visitor's
browser loading vendor scripts and firing requests to google-analytics.com, the browser
sends one request to a collection endpoint you control. A container running on your own
infrastructure receives it, transforms it, and forwards it server-to-server to whatever
destinations you configure.

The reason people reach for it is request origin. A request to google-analytics.com is on
every blocklist shipped with every content blocker. A request to metrics.yourdomain.com is
first-party, and Safari's Intelligent Tracking Prevention treats cookies set on that origin
differently from third-party ones. The mechanism is real. That is not the part under dispute.

What is under dispute is that "run a container" is doing an enormous amount of work in that
sentence. The container is a Docker image you host. Google publishes it; Google does not run
it for you.

What it really costs (infra + maintenance + specialist)

For the 20k-visit-per-month WordPress site that started this, here is what we actually put
on the page. Treat every figure as a range to verify against current pricing, not a quote.

Line item Setup Monthly Notes
Cloud Run tagging server $45–$120 Google's own guidance is a minimum of three instances for production; one always-on instance is not the recommended configuration.
Load balancer $18–$25 Required for a custom domain on the standard setup.
Custom subdomain + TLS ~$0 $0 Cheap, but it is a DNS change someone has to own.
Initial build $1,200–$3,500 Container deploy, client/tag configuration, consent wiring, QA against the existing setup.
Ongoing maintenance $150–$400 Container image updates, monitoring, breakage when a tag template changes.
Specialist availability The real cost. When it breaks, WordPress knowledge does not help you.

Call it $1,200–$3,500 up front and $210–$545 a month, on a site whose entire hosting bill was
$29. The infrastructure is not the expensive part, the last two rows are. A tagging server
is a production service. It has uptime, it has an owner, and when the owner leaves, the site
has a piece of critical measurement infrastructure that nobody on the team can debug.

That was the number that ended the conversation. Not because it was unaffordable, but because
nobody could explain what the site would get for it that it did not already have.

When it's worth it

It is worth it, and I want to be precise about when, because the sGTM-is-overkill
take is just as lazy as the everyone's-moving-to-it one.

Buy the container when you have multiple destinations. The moment you are fanning one
event out to several platforms, server-side, with different payload shapes and different
consent rules per destination, you want a transformation layer, and sGTM is a good one.

Buy it when you need transformation you cannot do at the source, enrichment from an
internal API, hashing, stripping fields for a data-residency requirement.

Buy it when someone owns it. If there is a person whose job includes this container, the
maintenance line item stops being a risk and becomes a salary you were already paying.

Buy it when the traffic maths works. At high volume, the infrastructure cost per event
collapses and the build cost amortises to nothing.

None of those were true for a WordPress site sending WooCommerce events to exactly one
destination.

When a plugin is enough

Here is the part that gets skipped. If your destination list is one item long and that item
is GA4, almost everything sGTM gives you is capability you are paying for and not using.

The transport problem, requests originating from your own domain instead of a blocked
third-party one, does not require a container. It requires an endpoint on your domain that
can accept an event and forward it server-to-server. WordPress already has one. The REST API
is first-party by definition, it is authenticated, and it runs on infrastructure you are
already paying for and already know how to debug.

The GA4 Measurement Protocol is a documented HTTP endpoint. A forwarded event is a POST with
a JSON body:

curl -X POST \
  "https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXX&api_secret=SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "1234567.7654321",
    "events": [{
      "name": "purchase",
      "params": {
        "transaction_id": "wc_8841",
        "currency": "EUR",
        "value": 129.95
      }
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

That is the entire protocol the container would have been speaking on your behalf. The hard
parts are not in that request. They are client_id continuity across the client/server
boundary, deduplication when both sides fire, consent state, and getting WooCommerce's
actual order data into the payload at the right point in the checkout lifecycle. Those are
WordPress problems, solved in WordPress, by code that already has access to the order object.

Decision table

sGTM container WordPress-side forwarding
Destinations Many, with per-destination logic One (GA4)
Monthly infrastructure $60–$145 $0 — your existing host
Build effort Days, specialist Minutes, setup wizard
Who debugs it at 2am A tagging specialist Whoever already maintains the site
Transformation layer Full None to speak of
Ceiling Very high You will outgrow it if you add destinations

We build the right-hand column. It is called Easy Server Side Tracking, it routes WordPress
and WooCommerce events through your own REST endpoint (or your own Cloudflare Worker, if you
want the edge version) to the GA4 Measurement Protocol, and it is free up to 10,000 events a
month with no signup to download it.

What this does not fix

Server-side delivery fixes the transport. It does not fix identity, and the difference
matters more than most write-ups admit.

It does not give you cross-device identity. A visitor on mobile and the same person on
desktop are still two people unless you have a login to tie them together.

It does not override consent. If someone denies consent, you do not get to track them by
moving the request server-side. That is the same processing with a different origin. Consent
Mode v2 and modelling are what you have, and modelled data is an estimate.

It does not undo ITP for returning visitors. First-party cookie lifetime limits still apply
to what the browser stores; a server-side endpoint changes where the request goes, not how
long Safari keeps the identifier.

And it does not repair history. Events that were dropped last quarter are gone. Nothing
recovers them retroactively. You are fixing the capture rate from today forward, which means
your year-over-year comparison will show a jump that is an artefact of the fix, not growth.
Annotate it, or you will misread your own dashboard in six months.

Where this fits

We did not set out to build a product. We set out to stop having the same conversation, which
went: the campaign worked, the report says it didn't, and the gap between those two facts is
now a budget decision. That campaign had skewed technical, its audience blocked more than
average, and it got cut on numbers that were bent rather than merely incomplete. The next
quarter's spend moved to a channel that measured better and converted worse, and by the time
the revenue reporting drifted far enough from the WooCommerce admin for anyone to notice, the
decision was two quarters old.

So we built the narrow thing. GA4 only, WordPress only. No multi-destination fan-out, no
transformation layer, no container to babysit. Everything we left out was left out on purpose,
because each one was a reason the site owner would need to call someone.

If you run it, run it in hybrid mode alongside your existing gtag.js for a week, dedup keys
mean nothing double-counts, and compare the two event counts. If it does not capture more
than what you have now, uninstall it. That is a real outcome and we would rather know.

What we actually want back is the breakage. Which WooCommerce extension writes an order in a
way that produces a purchase event you did not expect? That is the class of bug we cannot
find on our own machines.

Disclosure: I work on Easy Server Side Tracking, the plugin mentioned above.
The measurement method in this article works with any server-side setup.

Top comments (0)