First-party proxy · WordPress

Route the Admaxxer pixel through your WordPress site

Three parts: forwarding rules on your server, the Admaxxer plugin's Proxy Origin setting for the script, and a short filter that sends events through your domain as well, because the plugin's setting on its own only moves the script.

Self-run proxy · WordPress · Advanced

This guide assumes the Admaxxer WordPress plugin is installed with your Website ID. If you add the pixel to your theme by hand instead, follow the NGINX or Apache guide; they include the snippet to paste.

Why route the pixel through your own domain

What it doesn't change

Visitors who opt out stay opted out, and tools that inspect scripts on your own pages can still interfere. A proxy also changes which network address Admaxxer sees — read what Admaxxer sees through your proxy before you switch.

How the plugin's Proxy Origin works

In Settings → Admaxxer, the Proxy Origin field tells the plugin to load the tracking script from your own address instead of admaxxer.com. When you press Save Settings, the plugin first checks that the script really loads from that address and refuses one that doesn't, so a mistake can't switch your tracking off.

The setting moves the script, not the events

In the current plugin (version 1.4.1), Proxy Origin changes only where the script loads from. Events still go to admaxxer.com unless the script tag also carries data-proxy-origin, which Step 3 adds.

Before you start

Can't add proxy rules? Create a managed first-party subdomain instead (it needs only a DNS record), then follow Steps 2 and 3 below using your subdomain's address, such as https://t.yourdomain.com.

What your proxy must forward

With data-proxy-origin set, the pixel sends every request to that address instead of admaxxer.com. Forward each of these paths to the same path on https://admaxxer.com. A proxy that forwards only some of them silently loses data: custom events, purchases and identify calls each travel on a path of their own.

Path on your siteWhat uses itForward it
/js/script.jsThe tracking script the plugin loadsRequired
/api/eventPageviews, time on page, checkout-return detection, email identification and the install checkRequired
/api/event/batchCustom events, goals and purchases, sent in small batchesRequired
/api/identifyadmaxxer.identify(userId, traits) for signed-in usersRequired if you identify users
/api/pixel/adblocker-probe/<website ID>window.admaxxer.probe(), only if your own code calls itOptional

With the plugin's Enable Cookieless Tracking option on, it loads /js/script.cookieless.js instead; with Enable SPA Hash Mode, /js/script.hash.js. The rules below cover all three.

Pass requests through unchanged (same method, same JSON body), addressed to admaxxer.com in both the Host header and the TLS server name. Two browser headers must survive the trip:

Cookies aren't needed: the pixel sends its visitor and session IDs inside the request body.

Step 1: Add the forwarding rules

Apache (.htaccess)

Add this to the .htaccess file in your WordPress root, above the # BEGIN WordPress block. WordPress regenerates everything inside that block, and its catch-all rule would otherwise handle these paths first:

.htaccess

# Admaxxer first-party proxy: keep this above "# BEGIN WordPress".
# Needs mod_rewrite, mod_proxy, mod_proxy_http, and SSLProxyEngine on in the server configuration.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(js/script(\.cookieless|\.hash)?\.js|api/event|api/event/batch|api/identify)$ https://admaxxer.com/$1 [P,L]
</IfModule>

SSLProxyEngine on can't be set from .htaccess; whoever manages the server has to enable it. If the rule returns a 403 or 500, a required module or that setting is missing. The Apache guide has the details.

NGINX

Inside the HTTPS server { } block for your site, add these exact-match blocks, then run sudo nginx -t and reload NGINX. If you enabled cookieless or hash mode, change the first block's path to match. The NGINX guide explains each line.

# Admaxxer first-party proxy: inside the HTTPS server { } block for your site.
# Exact matches (=) take priority over every other location, so these never
# capture your own routes and can't be shadowed by a regex rule for .js files.
location = /js/script.js {
    proxy_pass https://admaxxer.com;
    proxy_set_header Host admaxxer.com;
    proxy_ssl_server_name on;
}
location = /api/event {
    proxy_pass https://admaxxer.com;
    proxy_set_header Host admaxxer.com;
    proxy_ssl_server_name on;
}
location = /api/event/batch {
    proxy_pass https://admaxxer.com;
    proxy_set_header Host admaxxer.com;
    proxy_ssl_server_name on;
}
location = /api/identify {
    proxy_pass https://admaxxer.com;
    proxy_set_header Host admaxxer.com;
    proxy_ssl_server_name on;
}

Step 2: Set the plugin's Proxy Origin

  1. In WordPress, open Settings → Admaxxer.
  2. In Proxy Origin, enter your site's address, such as https://yourdomain.com: the exact scheme and hostname your pages use, with no path.
  3. Press Save Settings. If the plugin reports that it couldn't load the script, the forwarding from Step 1 isn't working yet; the field stays blank and tracking carries on from admaxxer.com.

Step 3: Send events through your domain

Add this filter to your child theme's functions.php or a code-snippets plugin. It adds data-proxy-origin to the Admaxxer script tag so events follow the script onto your domain:

functions.php

// Send Admaxxer events through your own domain as well as the script.
// Use the same address you entered as the plugin's Proxy Origin.
add_filter( 'script_loader_tag', function ( $tag ) {
	$proxy_origin = 'https://yourdomain.com';
	if ( false === strpos( $tag, 'data-website-id=' ) || false !== strpos( $tag, 'data-proxy-origin=' ) ) {
		return $tag; // Not the Admaxxer tag, or already set.
	}
	return str_replace( ' src=', ' data-proxy-origin="' . esc_attr( $proxy_origin ) . '" src=', $tag );
}, 20 );

Step 4: Check that it works

Run these from any terminal, replacing yourdomain.com with your site's hostname:

# 1. The script loads through your domain: expect HTTP 200 and a JavaScript content type
curl -sI https://yourdomain.com/js/script.js

# 2. Each endpoint reaches Admaxxer. An empty body is rejected on purpose,
#    so nothing is recorded; the error reply proves the route works.
curl -s -X POST https://yourdomain.com/api/event -H 'Content-Type: application/json' -d '{}'
#    expect: {"error":"validation_failed", ...}
curl -s -X POST https://yourdomain.com/api/event/batch -H 'Content-Type: application/json' -d '{}'
#    expect: {"error":"empty_batch"}
curl -s -X POST https://yourdomain.com/api/identify -H 'Content-Type: application/json' -d '{}'
#    expect: {"error":"validation_failed", ...}

Only Admaxxer answers with those error messages. If you get your own site's 404 page or HTML instead, that path isn't being forwarded.

Then load your site with the browser's developer tools open on the Network tab. The script and the api/event requests should go to your own domain (none to admaxxer.com), and accepted events are answered with 202. Finally, open the pixel install page: the Verify install card turns green once events arrive.

Also view your page source: the Admaxxer script tag should load from your domain and carry both data-website-id and data-proxy-origin.

WooCommerce order events are sent by the plugin server-to-server and aren't affected by any of these steps.

What Admaxxer sees through your proxy

Visitors and sessions are counted from the IDs the pixel sends, so those numbers don't change. What changes is the network address: Admaxxer uses the address of whatever connects to it, and through a self-run proxy that is your proxy, not your visitor. Forwarding headers such as X-Forwarded-For are not used for this.

Troubleshooting

Self-run proxy or managed subdomain?

Admaxxer can also serve the pixel from a subdomain of yours with no proxy to run: in Integrations, open First-party tracking domain, add a subdomain such as t.yourdomain.com and create the one DNS record it shows. Both options load the pixel and send events from your own domain.

Managed first-party subdomainSelf-run proxy (this guide)
HostnameA subdomain, such as t.yourdomain.comThe hostname your site already uses
What you set upOne CNAME recordForwarding rules on your server, CDN or framework
Who keeps it runningAdmaxxerYou
SnippetShown in Admaxxer once DNS is verifiedWritten by you, from this guide

Choose a self-run proxy when you can't add DNS records, don't want a separate tracking subdomain, or need every request to pass through infrastructure you control. Otherwise the managed subdomain is less to maintain; see the first-party tracking domain guide.

Undo the setup

Put the standard snippet back first (copy it from the pixel install page), then clear the plugin's Proxy Origin field and press Save Settings, remove the Step 3 filter, and then remove the forwarding rules. In that order, no page ever points at a path that has stopped working.

Same setup on another platform: Cloudflare Workers · NGINX · Apache · Vercel · Next.js · Netlify · Nuxt

Frequently asked questions

Q: Isn't the plugin's Proxy Origin setting enough?

Not in plugin version 1.4.1: it moves only the script. Without data-proxy-origin on the tag, events are still sent to admaxxer.com, so the Step 3 filter is what makes events first-party too.

Q: Are my WooCommerce orders affected?

No. The plugin sends WooCommerce order events directly from your server to Admaxxer; the proxy only changes how visitors' browsers talk to Admaxxer.

Q: Do I need this if I set up a first-party tracking domain in Admaxxer?

No, use one or the other. Both make the pixel load and report from your own domain. The managed subdomain is set up in Admaxxer with one DNS record; a self-run proxy runs on your own server, CDN or framework.

Q: Will this stop ad blockers from blocking Admaxxer?

It removes admaxxer.com from every request, which is what hostname-based block lists match on. Blockers that inspect scripts or paths on your own site can still interfere, and visitors who opt out stay opted out.

Q: Why do all my visitors show up in one country?

Admaxxer can't see your visitors' network addresses through your proxy. It reads the country from a CF-IPCountry, X-Vercel-IP-Country or X-Real-Country header when one is passed along, and otherwise uses your proxy's location. Pass one of those headers with the visitor's two-letter country code.