In a hurry? Trigger a live GA4 event below.
To really master data tracking, you need to see exactly how the plumbing works under the hood. So, instead of using a standard managed hosting platform, I decided to build my own tracking environment completely from scratch.
This entire website is actually running on an Oracle Cloud Linux Virtual Machine that I provisioned myself. There is a simple 4-step process I used to get this online:
Server Setup: I set up the Linux VM and manually configured the cloud firewalls and iptables so the server is secure.
DNS Routing: I created A-records in my domain registrar and managed the DNS propagation to connect the domain to my server’s IP.
SSL Security: I secured the server traffic by installing a Let’s Encrypt SSL/TLS certificate.
Website Deployment: Finally, I deployed a WordPress instance using Nginx for caching and performance.
Why go through all this trouble? The problem with using standard managed platforms is that they act like a “black box.” In performance marketing, your data is everything. By completely owning the server infrastructure myself, I have total control over how Google Tag Manager and Google Analytics 4 (GA4) fire on this domain. I can track exact conversion events and build closed-loop attribution models without relying on third-party tools doing the work in the dark.
Now that the server is up and running, the next step is building the actual tracking pipeline.
There are 4 main components in this pipeline to build a robust, first-party data stream for Google Analytics.
Client-Side Tag (Web Container – Google Tag Manager)
Measurement Server (Stape.io Cloud Infrastructure)
Server-Side Tag (Server Container – Google Tag Manager)
Destination (Google Analytics 4)
1. The Client-Side Tag (The Dispatcher): In Google Tag Manager (GTM), I created a standard Web Container configured with my GA4 Measurement ID. GTM provides a Javascript snippet (container code) that I injected into my WordPress site’s header. Now, user actions on the site are tracked and stamped with my Analytics ID.
The Problem: By default, tracked data is sent directly to third-party servers (google-analytics.com). As browser environments become stricter with third-party tracking, relying purely on this standard method can lead to degraded tracking quality and data loss.
The Solution: We mitigate this by routing the data to our own server first. By keeping the tracking requests in a “first-party context,” we take full ownership of the data stream, improve overall accuracy, and reduce our reliance on fragile third-party cookies.
2. The Measurement Server (The First-Party Hub): This is the server our Web Container sends data to. While you can manually provision a server using Google’s Docker image, I opted for industry-standard cloud infrastructure using Stape.io.
I provisioned an sGTM (Server-Side Google Tag Manager) node in the AP-South region for optimal latency. To create the first-party context, I mapped a custom subdomain (data.santhoshk.com) to the Stape server using a CNAME record in my DNS (Porkbun). Finally, I updated my Web Container to route all analytics payloads to this new custom subdomain instead of Google.
3. The Server-Side Tag (The Secure Router): At this point, the Stape server is successfully receiving the data stream, but it operates as a transit hub—it doesn’t store data. We need to securely forward it to the final destination.
To handle this, I created a Server Container in GTM. I configured a custom trigger programmed to listen specifically for the GA4 Client (the protocol that translates the incoming data). I then linked a Server-Side GA4 Tag to this trigger. Now, whenever the server receives data stamped with my Measurement ID, it automatically securely forwards the payload directly to Google Analytics 4.
4. Google Analytics 4 (The Destination): With the closed-loop pipeline complete, the clean, first-party data stream flows into the GA4 property. From here, I can configure custom events, analyze user behavior, and attribute conversions accurately without relying on a “black box” pixel.