Server-Side Tracking, Tutorials & Guides

How to Set Up Server-Side Tracking on Your Own VPS (Step-by-Step)

Admin4/11/2026👁️ 12 views

A complete step-by-step guide to self-hosting server-side GTM on a VPS. Covers Docker setup, Nginx reverse proxy, SSL, and ongoing maintenance.

How to Set Up Server-Side Tracking on Your Own VPS (Step-by-Step)

Server-side tracking has become the standard for accurate conversion data. But managed hosting services charge monthly fees that add up fast — especially when you are running multiple domains or handling high traffic volumes.

If you have a VPS (Virtual Private Server) running Ubuntu, you can host your own server-side Google Tag Manager container for the cost of the server itself. No third-party platform fees. Full control over your infrastructure, your data, and your uptime.

This guide walks you through the entire process — from a fresh Ubuntu VPS to a working server-side GTM setup with Docker, Nginx, SSL, and a custom subdomain. Every step includes the actual SSH commands you will run. No hand-waving, no skipped steps.

Whether you are a developer setting this up for your own ecommerce store, an agency building infrastructure for clients, or a technical marketer who wants to understand what happens under the hood — this is the reference you need.

Table of Contents

What You Need Before Starting

Before you SSH into your server, make sure you have the following ready:

  • A VPS running Ubuntu 22.04 or 24.04 LTS — from any provider (Contabo, DigitalOcean, Vultr, Hetzner, Linode, AWS EC2, etc.). Minimum 1 vCPU and 1 GB RAM is sufficient for low-to-moderate traffic. Google's documentation notes that the tagging server uses at most 1 vCPU — additional vCPUs are not utilized and can affect autoscaling negatively.
  • A registered domain name — you will create a subdomain like track.yourdomain.com or gtm.yourdomain.com to point to your VPS.
  • SSH access — you need to be able to connect to your VPS via terminal.
  • A Google Tag Manager server container — created in your GTM account (we will cover how to get the config string).
  • Basic command line comfort — you don't need to be a Linux expert, but you should be comfortable running commands in a terminal.

How the Architecture Works

Before running any commands, it helps to understand what you are building. Google's server-side tagging runs as a Node.js application packaged inside a Docker image. You will run two separate Docker containers on your VPS:

  1. Preview Server — used by GTM's preview/debug mode. You need exactly one instance. It must not be autoscaled.
  2. Tagging Server (SST) — the production entry point that handles all incoming tracking requests. This is what your website sends data to. It proxies preview requests to the preview server and processes everything else.

In front of these containers, you will run Nginx as a reverse proxy that handles SSL termination and routes external HTTPS requests to the correct Docker container on localhost. Visitors and browsers only interact with Nginx — they never touch the Docker containers directly.

The data flow looks like this:

Browser → track.yourdomain.com (Nginx + SSL) → Docker tagging container (port 8080) → Platforms (GA4, Meta, Google Ads, etc.)

Step 1: Prepare Your Ubuntu VPS

Connect to your VPS via SSH:

ssh root@YOUR_SERVER_IP

If you use an SSH key (recommended):

ssh -i ~/.ssh/your_key root@YOUR_SERVER_IP

Once connected, update the system packages:

sudo apt update && sudo apt upgrade -y

Install essential utilities:

sudo apt install -y curl wget git ufw nano

Set up the firewall to allow SSH, HTTP, and HTTPS traffic:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

When prompted, type y to confirm enabling the firewall.

Step 2: Install Docker

Google's server-side tagging server is distributed as a Docker image. Install Docker using the official method:

# Remove any old versions
sudo apt remove -y docker docker-engine docker.io containerd runc

# Install prerequisites
sudo apt install -y ca-certificates curl gnupg

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Verify Docker is running
sudo docker run hello-world

You should see a "Hello from Docker!" message confirming the installation succeeded.

Optionally, add your user to the docker group so you don't need sudo for every docker command:

sudo usermod -aG docker $USER

Log out and back in for this to take effect.

Step 3: Get Your GTM Container Config String

This step happens in your browser, not in the terminal.

  1. Go to tagmanager.google.com.
  2. If you don't already have a server container, create one: click Create Container, name it (e.g., "My Server Container"), and select Server as the target platform.
  3. Once in the server container workspace, click the Container ID in the top-right corner of the page.
  4. Click "Manually provision tagging server".
  5. Copy the Container Config string. It will look something like: aW50ZXJuYWwtYXV0aC... (a long Base64-encoded string).

Save this string — you will use it in the next two steps.

Step 4: Run the Preview Server

Back in your SSH terminal, pull the official GTM server-side Docker image and start the preview server:

# Pull the latest stable image
sudo docker pull gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

# Run the preview server on port 8081
sudo docker run -d \
  --name gtm-preview \
  --restart unless-stopped \
  -p 8081:8080 \
  -e CONTAINER_CONFIG='YOUR_CONTAINER_CONFIG_STRING' \
  -e RUN_AS_PREVIEW_SERVER=true \
  gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

Replace YOUR_CONTAINER_CONFIG_STRING with the actual config string you copied from GTM.

Verify it is running:

curl http://localhost:8081/healthy

You should get a 200 OK response. If you see an error, check the container logs:

sudo docker logs gtm-preview

Important: You must run exactly one preview server instance. Do not scale this to multiple instances.

Step 5: Run the Tagging Server

Now start the main tagging server. This container will handle all production tracking requests:

sudo docker run -d \
  --name gtm-tagging \
  --restart unless-stopped \
  -p 8080:8080 \
  -e CONTAINER_CONFIG='YOUR_CONTAINER_CONFIG_STRING' \
  -e PREVIEW_SERVER_URL='https://track.yourdomain.com/preview/' \
  gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

Note: The PREVIEW_SERVER_URL needs to be the HTTPS URL where your preview server will be accessible. We haven't set up SSL yet, so use the URL you plan to configure (we will set it up in Steps 7 and 8). You may need to restart this container after SSL is configured.

Verify the tagging server:

curl http://localhost:8080/healthy

Again, a 200 OK response means the container is running correctly.

Step 6: Set Up Your Custom Subdomain

Go to your domain registrar's DNS management panel (Namecheap, Cloudflare, GoDaddy, or wherever your domain DNS is managed) and create an A record:

Type Host Value TTL
A track YOUR_SERVER_IP Auto or 1800

This creates track.yourdomain.com pointing to your VPS. You can use any subdomain name — gtm, data, analytics, ss — but track is the most common convention.

Wait for DNS propagation (usually 5–30 minutes). You can check with:

dig track.yourdomain.com +short

This should return your server's IP address.

Why this matters for tracking: Google recommends hosting your server-side tagging endpoint on the same origin or as a subdomain of your website. When the tracking subdomain shares the same registrable domain as your site, cookies set by the server are treated as genuine first-party cookies — which is critical for bypassing Safari ITP restrictions and extending cookie lifetimes.

Step 7: Install Nginx as a Reverse Proxy

Nginx will sit in front of your Docker containers, handle SSL, and route requests to the correct container:

sudo apt install -y nginx

Create a new Nginx configuration file for your tracking subdomain:

sudo nano /etc/nginx/sites-available/track.yourdomain.com

Paste the following configuration (replace track.yourdomain.com with your actual subdomain):

server {
    listen 80;
    server_name track.yourdomain.com;

    # Preview server — route /preview/ to port 8081
    location /preview/ {
        proxy_pass http://127.0.0.1:8081/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }

    # Tagging server — route everything else to port 8080
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the site and test the configuration:

# Create a symlink to enable the site
sudo ln -s /etc/nginx/sites-available/track.yourdomain.com /etc/nginx/sites-enabled/

# Test Nginx configuration for syntax errors
sudo nginx -t

# If the test passes, reload Nginx
sudo systemctl reload nginx

At this point, http://track.yourdomain.com/healthy should return a 200 response (over plain HTTP — we will add SSL next).

Step 8: Install SSL with Let's Encrypt

Server-side tracking requires HTTPS. The preview server URL must be HTTPS, and browsers will only send data to HTTPS endpoints. Let's Encrypt provides free SSL certificates via Certbot:

# Install Certbot and the Nginx plugin
sudo apt install -y certbot python3-certbot-nginx

# Obtain and install the certificate
sudo certbot --nginx -d track.yourdomain.com

Certbot will ask for your email address (for renewal notifications) and whether to redirect HTTP to HTTPS. Select yes to redirect — all tracking requests should go over HTTPS.

Verify the certificate installed correctly:

curl -I https://track.yourdomain.com/healthy

You should see HTTP/2 200 with a valid SSL connection.

Certbot automatically sets up a cron job for auto-renewal. You can test it with:

sudo certbot renew --dry-run

Step 9: Configure GTM and Verify

Now that your server is running with SSL, update the tagging server's preview URL. First, stop and remove the tagging container, then restart it with the correct HTTPS preview URL:

# Stop and remove the old tagging container
sudo docker stop gtm-tagging
sudo docker rm gtm-tagging

# Restart with the correct HTTPS preview URL
sudo docker run -d \
  --name gtm-tagging \
  --restart unless-stopped \
  -p 8080:8080 \
  -e CONTAINER_CONFIG='YOUR_CONTAINER_CONFIG_STRING' \
  -e PREVIEW_SERVER_URL='https://track.yourdomain.com/preview/' \
  gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

Now configure GTM to use your server:

  1. In Google Tag Manager, go to your server container.
  2. Navigate to Admin → Container Settings.
  3. Enter https://track.yourdomain.com in the Server container URL field.
  4. Click Save.
  5. Click the Preview button in your workspace.
  6. In a separate browser tab, visit https://track.yourdomain.com.
  7. If the preview panel shows the request, your setup is working correctly.

Step 10: Run Containers on Startup

The --restart unless-stopped flag we used earlier ensures Docker restarts the containers if they crash or if the server reboots. But let's make sure Docker itself starts on boot:

sudo systemctl enable docker

Verify both containers are running:

sudo docker ps

You should see both gtm-preview and gtm-tagging listed with status "Up".

To check resource usage:

sudo docker stats --no-stream

This shows CPU and memory usage for each container. For a low-traffic site, expect minimal resource consumption — well under 512 MB combined.

Ongoing Maintenance

Self-hosting means you are responsible for keeping things running. Here is what ongoing maintenance looks like:

Update the Docker Image

Google periodically releases updated versions of the gtm-cloud-image with security patches and new features. Check for updates at least monthly:

# Pull the latest image
sudo docker pull gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

# Recreate the preview server
sudo docker stop gtm-preview && sudo docker rm gtm-preview
sudo docker run -d \
  --name gtm-preview \
  --restart unless-stopped \
  -p 8081:8080 \
  -e CONTAINER_CONFIG='YOUR_CONTAINER_CONFIG_STRING' \
  -e RUN_AS_PREVIEW_SERVER=true \
  gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

# Recreate the tagging server
sudo docker stop gtm-tagging && sudo docker rm gtm-tagging
sudo docker run -d \
  --name gtm-tagging \
  --restart unless-stopped \
  -p 8080:8080 \
  -e CONTAINER_CONFIG='YOUR_CONTAINER_CONFIG_STRING' \
  -e PREVIEW_SERVER_URL='https://track.yourdomain.com/preview/' \
  gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable

Monitor Server Health

Set up a simple health check. You can use a free uptime monitoring service or a cron job:

# Add to crontab: check health every 5 minutes
(crontab -l 2>/dev/null; echo "*/5 * * * * curl -sf https://track.yourdomain.com/healthy > /dev/null || systemctl restart docker") | crontab -

This checks the health endpoint every 5 minutes and restarts Docker if the server stops responding.

Keep Ubuntu Updated

# Run monthly or set up unattended upgrades
sudo apt update && sudo apt upgrade -y

SSL Certificate Renewal

Certbot handles this automatically. Certificates renew every 90 days. Verify the auto-renewal timer is active:

sudo systemctl status certbot.timer

Common Mistakes to Avoid

After working with many server-side tracking setups, these are the errors that come up most frequently:

  • Using HTTP instead of HTTPS for the preview URL. The PREVIEW_SERVER_URL environment variable must be an HTTPS URL. If you set it to http://, preview mode will fail silently and you will spend hours debugging.
  • Forgetting to open firewall ports. If you configured UFW but forgot to allow Nginx traffic, external requests will timeout. Always run sudo ufw allow 'Nginx Full' before testing.
  • Running multiple preview server instances. Google explicitly states you must run exactly one preview server. Scaling it will break preview mode.
  • Not setting the server container URL in GTM. The setup isn't complete until you enter your https://track.yourdomain.com URL in GTM's Admin → Container Settings → Server container URL field.
  • Ignoring Docker image updates. The gtm-cloud-image receives regular updates. Running a months-old version can cause compatibility issues with new GTM features and may have unpatched security vulnerabilities.
  • Using a shared IP that triggers Safari ITP. If your VPS IP is used by many other tracking setups (common on cheap shared hosting), Safari's Intelligent Tracking Prevention may flag it and cap your cookie lifetime to 7 days. Dedicated IPs are preferred.
  • Skipping event deduplication. If you send events from both the browser (Meta Pixel, GA4 tag) and the server (Meta CAPI, GA4 Measurement Protocol), you must include matching event_id values. Without this, conversions are double-counted.

Self-Hosted vs Managed Hosting: When Each Makes Sense

Self-hosting your server-side GTM on a VPS gives you maximum control and can be cost-effective — especially if you already have server infrastructure. But it requires you to handle Docker updates, SSL renewals, server monitoring, security patches, and troubleshooting when something breaks at 2 AM.

Managed server-side GTM hosting services handle all of this for you. You get a working server container without managing infrastructure. The tradeoff is a monthly fee on top of any server costs.

Factor Self-Hosted VPS Managed Hosting
Monthly cost VPS cost only ($5–$10/mo for most sites) Provider fee ($20–$200+/mo depending on plan)
Setup effort High — follow this guide step by step Low — often one-click or guided setup
Maintenance You handle Docker updates, SSL, server patches Provider handles everything
Customization Full control over server config, ports, firewall Limited to provider's options
Troubleshooting You debug issues yourself Support team helps
Best for Developers, agencies with DevOps capability Marketers, store owners, teams without server admins

If you want the tracking benefits of server-side GTM without managing infrastructure, ServerPixel BD offers managed server-side GTM hosting with setup support — including Meta CAPI configuration, GA4 server-side setup, custom domain provisioning, and ongoing maintenance. You can start with a free trial to test the infrastructure before committing.

If you prefer to manage your own servers and follow the steps in this guide, that works too. The tracking benefits are the same either way — what differs is who maintains the infrastructure.

Conclusion

Setting up server-side tracking on your own VPS is not a five-minute job, but it is entirely achievable with the steps in this guide. Once running, you get the same tracking benefits as any managed solution — first-party cookies, ad blocker resilience, server-to-server data transfer for Meta CAPI and GA4 — at a fraction of the ongoing cost.

The key is proper setup and consistent maintenance. Use HTTPS everywhere. Keep Docker images updated. Monitor the health endpoint. Set up event deduplication if you run both browser and server-side tags.

If you followed every step in this guide and something isn't working, check the Docker logs (docker logs gtm-tagging), verify your DNS is resolving, and confirm your CONTAINER_CONFIG string is correct. Most issues come down to one of those three things.

For those who want the tracking benefits without the server management, ServerPixel BD's managed hosting handles the infrastructure so you can focus on what the data tells you rather than how the server runs. Start a free trial or learn more about how we work.

Either way — self-hosted or managed — server-side tracking is the foundation for accurate conversion data in 2026 and beyond. The browser-only era of tracking is ending. Building the infrastructure now puts you ahead.


This guide is maintained by the ServerPixel BD team. We provide server-side GTM hosting, Meta Conversions API setup, GA4 server-side implementation, and tracking infrastructure for ecommerce businesses and agencies. For questions or corrections, reach out at admin@serverpixelbd.com.

Last updated: April 2026

Related reading:

Frequently Asked Questions

For most small-to-medium traffic sites, 1 vCPU and 1 GB RAM is sufficient. Google's documentation notes that the tagging server uses at most 1 vCPU. If you handle heavy traffic (millions of requests per month), consider 2 GB RAM and monitor resource usage with <code>docker stats</code>.

Tags

#server-side tracking#server-side GTM#Google Tag Manager#Docker#Ubuntu#VPS setup#Nginx#Let's Encrypt#SSL#Meta CAPI#GA4#first-party cookies#self-hosted tracking#server-side tagging#conversion tracking#sGTM

Need help with server-side tracking?

Explore ServerPixel BD services, plugins, and tracking solutions to improve data accuracy and marketing performance.