Chris Tam · Last updated 16 October 2026
WordPress builds public pages on the server, and its plugin system lets you keep tracking separate from a theme. Web analytics connects those visits to the pages and campaigns that brought people there.
In this tutorial, I'll install the shared plugin, create Home and Pricing pages, and follow a tagged visit into Amplitude.
What you'll build
A WordPress plugin that loads Amplitude on public pages, with automatic page views, sessions, and a campaign-tagged test visit.
Prerequisites
- A staging WordPress site with permission to upload a custom plugin and edit
wp-config.php. This tutorial uses a plugin you control. On managed hosting, confirm that your plan permits those changes. - WordPress 6.3 or later and PHP 7.4 or later, plus a theme that calls
wp_head()andwp_footer(). The executable example was tested on WordPress 6.9.10 and PHP 8.3.33. - An Amplitude project API key: Settings > Projects > your project > General > Manage next to API Key. Managers and Admins can view it. The browser key is public and limited to the minimum scope needed for ingestion. Keep secret keys out of this plugin.
A free Amplitude account covers this example within its product limits. Sign up for free to get your project API key.
1. Install the shared WordPress plugin
Create wp-content/plugins/amplitude-build/. Add these two files, then activate Amplitude Build Examples in Plugins. This uses the Amplitude browser snippet through WordPress's script queue. If you already installed the shared plugin, merge additions into it and keep its one initializer.
The PHP file owns loading. It puts analytics.js inline immediately after the synchronous project loader. Do not add async or defer, or move initialization into a separately downloaded script. Exclude these handles and their inline configuration from an optimizer that delays or reorders scripts. The optional sibling files load only after you create them.
<?php
/**
* Plugin Name: Amplitude Build Examples
* Description: Front-end instrumentation for the WordPress Build tutorials.
* Version: 1.0.0
* Requires at least: 6.3
* Requires PHP: 7.4
*/
// Keep sibling additions: analytics.js replay privacy, demo.php and events.js
// (/build/wordpress-product-analytics), engagement.php (/build/wordpress-guides-surveys),
// experiment-consent.js (/build/wordpress-web-experiment).
defined('ABSPATH') || exit;
add_action('wp_enqueue_scripts', function () {
if (!defined('AMP_BUILD_API_KEY') || !is_string(AMP_BUILD_API_KEY) || trim(AMP_BUILD_API_KEY) === '') {
return;
}
$zone = defined('AMP_BUILD_SERVER_ZONE') && AMP_BUILD_SERVER_ZONE === 'EU' ? 'EU' : 'US';
$host = $zone === 'EU' ? 'https://cdn.eu.amplitude.com' : 'https://cdn.amplitude.com';
wp_enqueue_script('amp-build-sdk', $host . '/script/' . rawurlencode(AMP_BUILD_API_KEY) . '.js', array(), null, false);
wp_add_inline_script('amp-build-sdk', 'window.ampBuildConfig = ' . wp_json_encode(array(
'apiKey' => AMP_BUILD_API_KEY,
'serverZone' => $zone,
), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) . ';', 'before');
if (file_exists(__DIR__ . '/experiment-consent.js')) {
wp_add_inline_script('amp-build-sdk', file_get_contents(__DIR__ . '/experiment-consent.js'), 'before');
}
// Inline init must stay immediately after the synchronous project loader.
wp_add_inline_script('amp-build-sdk', file_get_contents(__DIR__ . '/analytics.js'), 'after');
if (file_exists(__DIR__ . '/events.js')) {
wp_enqueue_script('amp-build-events', plugins_url('events.js', __FILE__), array('amp-build-sdk'), (string) filemtime(__DIR__ . '/events.js'), true);
}
}, 10);
foreach (array('demo.php', 'engagement.php') as $addition) {
if (file_exists(__DIR__ . '/' . $addition)) {
require_once __DIR__ . '/' . $addition;
}
}// wp-content/plugins/amplitude-build/analytics.js
// Keep sibling additions: replay privacyConfig (/build/wordpress-session-replay).
(() => {
if (window.ampBuildReady) return;
if (!window.amplitude || !window.sessionReplay) {
console.warn('Amplitude did not load. Check the CDN request and site policy.');
return;
}
const config = window.ampBuildConfig;
const replayOptions = { sampleRate: 1, serverZone: config.serverZone };
window.amplitude.add(window.sessionReplay.plugin(replayOptions));
window.ampBuildReady = window.amplitude.init(config.apiKey, {
serverZone: config.serverZone,
remoteConfig: { fetchRemoteConfig: true },
autocapture: {
attribution: true,
pageViews: { trackHistoryChanges: 'pathOnly' },
sessions: true,
formInteractions: true,
fileDownloads: true,
elementInteractions: false,
frustrationInteractions: false,
networkTracking: false,
webVitals: false
}
}).promise;
})();Add the public project key in wp-config.php, above the line that loads wp-settings.php. Replace AMPLITUDE_API_KEY with your key. Keep the existing database and security configuration.
// wp-config.php: add before WordPress loads wp-settings.php.
define('AMP_BUILD_API_KEY', 'AMPLITUDE_API_KEY');
define('AMP_BUILD_SERVER_ZONE', 'US'); // Use EU for an EU project.The sample requests replay capture for every synthetic test session. Before production, choose your intended sampleRate, such as 0.01, or 0 to request no replay capture, and inspect remote capture settings and quota. Remote settings can override local options. The project-specific loader also includes Web Experiment; guides and surveys use a separate script. For an EU project, the PHP file selects the EU CDN and the initializer sets the EU server zone.
If your consent policy requires no collection or storage before permission, configure your consent platform to defer the entire integration, including the project loader. Loading this script and postponing only your own init call is insufficient because the project loader can initialize automatically. Verify consent on the deployed site; the static example assumes permission to run on your synthetic staging site.
2. Publish Home and Pricing
Create two published Pages: Home and Pricing, with the Pricing slug pricing. In Settings > Reading, choose Home as the static front page. Use a permalink structure that produces /pricing/. Add ordinary navigation links in Custom HTML blocks, or use equivalent WordPress links.
<!-- Home and Pricing: Custom HTML navigation block -->
<nav aria-label="Test navigation"><a href="/">Home</a> <a href="/pricing/">Pricing</a></nav>Visit both public URLs. WordPress links normally load a new document. Autocapture sends that page's view, so don't send another page view from a navigation click handler. pathOnly also supports History API path changes without treating hash-only changes as a new page view.
3. Make a campaign-tagged test visit
Open Home with these parameters, replacing the origin with your staging address. Preserve them through redirects before the SDK loads.
# Browser address bar
https://YOUR-STAGING-SITE.example/?utm_source=build_qa&utm_medium=test&utm_campaign=wordpress-build-qaInspect attribution user properties such as utm_source and utm_campaign in Instrumentation Explorer. The managed CDN can serve a different SDK version from the latest npm release; inspect the version and actual attribution fields instead of assuming new defaults. Follow Pricing through its internal link without adding campaign tags to that link.
4. Check identity across page loads
Run this on Home, then on Pricing and after a refresh. Compare the device ID in the same browser and origin.
// Browser Console on the public WordPress site
window.amplitude.getDeviceId();
window.amplitude.flush();Use separate checks for staging and production hosts. Deliberate cross-domain identity configuration is a separate task.
MCP: Ask your coding agent to inspect the project's event taxonomy with the Amplitude MCP server before adding events. Reuse existing names when they describe the same action.
Verify it worked
- WordPress output: Open the public staging page while logged out. Check that the project loader appears once and its inline initialization follows it. After deployment or configuration changes, purge the relevant page and CDN caches.
- Network: Confirm an event POST receives HTTP 200 from
api2.amplitude.comfor US projects orapi.eu.amplitude.comfor EU projects. Large batches can be compressed; use this check for delivery status. - Instrumentation Explorer: Inspect event names, properties, counts, and
device_idin the Chrome extension. Compare one action with one expected custom event. - User Profiles: Search that device ID in Amplitude and inspect its event stream. The docs describe a delay of ten seconds to one minute. Data > Sources > Ingestion Debugger shows request and event counts, rather than individual event payloads.
Troubleshooting
The plugin is active but no SDK loads
Check that AMP_BUILD_API_KEY is defined before wp-settings.php, then inspect the public page source. This plugin uses the front-end enqueue hook, so its SDK is absent from the WordPress login and administration pages.
The script order differs from the example
Check caching and script-optimization exclusions for amp-build-sdk and amp-build-engagement. The project loader and inline initialization must remain together. Check for an earlier installation in a theme, tag manager, or snippet plugin.
Requests are blocked
Check the key, region, browser extensions, and Console. Follow the relevant SDK's CSP and endpoint guidance while preserving your site's security policy.
Autocapture settings differ from the file
Review Data > Settings > Autocapture. When remote configuration is enabled, remote values take precedence for the features they specify.
FAQ
Will changing the theme remove this integration?
The code lives in its own plugin. Keep the plugin active and use a theme with the standard head and footer hooks.
Do I add this to every page in the block editor?
The plugin enqueues the SDK on public pages. Use the editor for navigation and page content, while keeping one shared SDK installation.
Full code reference
Optional files added by sibling tutorials; keep them if installed: demo.php, events.js, engagement.php, experiment-consent.js. Merge the changes into existing files; preserve sibling additions named in the comments.
<?php
/**
* Plugin Name: Amplitude Build Examples
* Description: Front-end instrumentation for the WordPress Build tutorials.
* Version: 1.0.0
* Requires at least: 6.3
* Requires PHP: 7.4
*/
// Keep sibling additions: analytics.js replay privacy, demo.php and events.js
// (/build/wordpress-product-analytics), engagement.php (/build/wordpress-guides-surveys),
// experiment-consent.js (/build/wordpress-web-experiment).
defined('ABSPATH') || exit;
add_action('wp_enqueue_scripts', function () {
if (!defined('AMP_BUILD_API_KEY') || !is_string(AMP_BUILD_API_KEY) || trim(AMP_BUILD_API_KEY) === '') {
return;
}
$zone = defined('AMP_BUILD_SERVER_ZONE') && AMP_BUILD_SERVER_ZONE === 'EU' ? 'EU' : 'US';
$host = $zone === 'EU' ? 'https://cdn.eu.amplitude.com' : 'https://cdn.amplitude.com';
wp_enqueue_script('amp-build-sdk', $host . '/script/' . rawurlencode(AMP_BUILD_API_KEY) . '.js', array(), null, false);
wp_add_inline_script('amp-build-sdk', 'window.ampBuildConfig = ' . wp_json_encode(array(
'apiKey' => AMP_BUILD_API_KEY,
'serverZone' => $zone,
), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) . ';', 'before');
if (file_exists(__DIR__ . '/experiment-consent.js')) {
wp_add_inline_script('amp-build-sdk', file_get_contents(__DIR__ . '/experiment-consent.js'), 'before');
}
// Inline init must stay immediately after the synchronous project loader.
wp_add_inline_script('amp-build-sdk', file_get_contents(__DIR__ . '/analytics.js'), 'after');
if (file_exists(__DIR__ . '/events.js')) {
wp_enqueue_script('amp-build-events', plugins_url('events.js', __FILE__), array('amp-build-sdk'), (string) filemtime(__DIR__ . '/events.js'), true);
}
}, 10);
foreach (array('demo.php', 'engagement.php') as $addition) {
if (file_exists(__DIR__ . '/' . $addition)) {
require_once __DIR__ . '/' . $addition;
}
}// wp-content/plugins/amplitude-build/analytics.js
// Keep sibling additions: replay privacyConfig (/build/wordpress-session-replay).
(() => {
if (window.ampBuildReady) return;
if (!window.amplitude || !window.sessionReplay) {
console.warn('Amplitude did not load. Check the CDN request and site policy.');
return;
}
const config = window.ampBuildConfig;
const replayOptions = { sampleRate: 1, serverZone: config.serverZone };
window.amplitude.add(window.sessionReplay.plugin(replayOptions));
window.ampBuildReady = window.amplitude.init(config.apiKey, {
serverZone: config.serverZone,
remoteConfig: { fetchRemoteConfig: true },
autocapture: {
attribution: true,
pageViews: { trackHistoryChanges: 'pathOnly' },
sessions: true,
formInteractions: true,
fileDownloads: true,
elementInteractions: false,
frustrationInteractions: false,
networkTracking: false,
webVitals: false
}
}).promise;
})();Hand it to your agent
Point your agent at https://amplitude.com/build/wordpress-web-analytics.
Agent task: WordPress web analytics.
Create the shared WordPress plugin and wp-config constants. Preserve sibling files, replay privacy, engagement registration, consent code, and event handlers. Keep inline analytics init immediately after the synchronous project loader. Test public Home and Pricing pages, campaign properties, device continuity, duplicate installation, and cache behavior. Do not instrument wp-admin or wp-login. Gate the entire integration on consent when required.What this unlocks
Product analytics measures the accepted-form outcome when Demo Form Accepted is installed.
Session replay shows the interaction around the test form after capture and masking are verified.
Web Experiment can use Demo Form Accepted as a conversion metric.
Guides and surveys can ask a visitor what they need on Pricing after targeting is configured.