---
title: "How to add web analytics to a WordPress site"
description: "Add Amplitude web analytics to WordPress through a small plugin. Check page views, campaign attribution, and visitor continuity."
canonical: "https://amplitude.com/en-us/build/wordpress-web-analytics"
---

# How to add web analytics to a WordPress site

Add Amplitude web analytics to WordPress through a small plugin. Check page views, campaign attribution, and visitor continuity.

Source: https://amplitude.com/en-us/build/wordpress-web-analytics

---

# How to add web analytics to a WordPress site

Add Amplitude web analytics to WordPress through a small plugin. Check page views, campaign attribution, and visitor continuity.

- WordPress 6.3+
- Custom plugin
- Browser SDK 2
- CDN
- 20 min

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](https://amplitude.com/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()` and `wp_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](https://app.amplitude.com/signup) 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](https://amplitude.com/docs/get-started/amplitude-quickstart) through WordPress's [script queue](https://developer.wordpress.org/reference/functions/wp_enqueue_script/). 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.

wp-content/plugins/amplitude-build/amplitude-build.php

```php
<?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

```javascript
// 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.

```php
// 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

```html
<!-- 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

```text
# Browser address bar
https://YOUR-STAGING-SITE.example/?utm_source=build_qa&utm_medium=test&utm_campaign=wordpress-build-qa
```

Inspect 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

```javascript
// 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](https://amplitude.com/docs/amplitude-ai/amplitude-mcp) before adding events. Reuse existing names when they describe the same action.

## Verify it worked

1. **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.
2. **Network:** Confirm an event POST receives HTTP 200 from `api2.amplitude.com` for US projects or `api.eu.amplitude.com` for EU projects. Large batches can be compressed; use this check for delivery status.
3. **Instrumentation Explorer:** Inspect event names, properties, counts, and `device_id` in the Chrome extension. Compare one action with one expected custom event.
4. **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.

wp-content/plugins/amplitude-build/amplitude-build.php

```php
<?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

```javascript
// 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 prompt

```text
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](https://amplitude.com/amplitude-analytics) measures the accepted-form outcome when `Demo Form Accepted` is installed.

[Session replay](https://amplitude.com/session-replay) shows the interaction around the test form after capture and masking are verified.

[Web Experiment](https://amplitude.com/web-experimentation) can use `Demo Form Accepted` as a conversion metric.

[Guides and surveys](https://amplitude.com/guides-and-surveys) can ask a visitor what they need on Pricing after targeting is configured.

## Next steps

[WordPressHow to add product analytics to a WordPress siteTrack a WordPress pricing CTA and a form accepted by the server. Verify a saved acceptance record before counting the conversion.](/build/wordpress-product-analytics)[WordPressHow to add session replay to a WordPress siteConfigure replay masking in the WordPress plugin. Record a synthetic visit and verify its content and analytics association.](/build/wordpress-session-replay)[WordPressHow to add Web Experiment to a WordPress siteConfigure a WordPress CTA copy test with Amplitude Web Experiment. Preview variants and check impressions and accepted form conversions.](/build/wordpress-web-experiment)

Reference docs

[Amplitude quickstart →](https://amplitude.com/docs/get-started/amplitude-quickstart)[Browser sdk 2 →](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2)[Debug analytics →](https://amplitude.com/docs/analytics/debug-analytics)[Keys and tokens →](https://amplitude.com/docs/apis/keys-and-tokens)[WordPress script queue →](https://developer.wordpress.org/reference/functions/wp_enqueue_script/)[WordPress inline scripts →](https://developer.wordpress.org/reference/functions/wp_add_inline_script/)

For agents

[View raw .md](/build/wordpress-web-analytics.md)[llms.txt](/llms.txt)

## Add Amplitude to your WordPress site

Start with one shared plugin and follow the tutorials for each product.

[Create a free account](https://app.amplitude.com/signup)[Browse all Build tutorials](https://amplitude.com/build)
