Install on WordPress

View as Markdown

Paste one script tag into your site's header, clear your cache, and open the site. You can do it with a header-snippet plugin (no code) or from a child theme.

Platform steps checked against the official documentation on 2026-11-03: WPCode: Using the global Header & Footer settings, WPCode plugin page, WordPress: Child themes, WordPress: wp_head, WordPress: get_current_user_id(), WordPress: is_user_logged_in(), WP Rocket: Delay JavaScript execution exclusions.

Quick install

Settings › Channels in the Telltale dashboard shows this tag with your real key already filled in. Copy it from there.

HTML
<script src="https://app.trytelltale.dev/sdk/v1.js" data-telltale-key="YOUR_SITE_PUBLISHABLE_KEY"></script>

With a plugin (no code)

This uses WPCode ("Insert Headers and Footers"), a free plugin from the WordPress plugin directory. Any plugin that adds code to every page's <head> works the same way.

  1. In your WordPress admin, go to Plugins › Add New Plugin, search for WPCode, then choose Install Now and Activate.
  2. Go to Code Snippets › Header & Footer.
  3. Paste the tag into the Header box.
  4. Choose Save Changes.
  5. If you use a caching plugin or your host caches pages, clear the cache (see Common mistakes).

If you switched WPCode to its simple "Headers & Footers mode", the same boxes are under Settings › Header & Footer.

From a child theme

If you maintain a child theme, print the tag from its functions.php. Never edit the parent theme: a theme update overwrites it.

php
// wp-content/themes/your-child-theme/functions.php
add_action( 'wp_head', function () {
	printf(
		'<script src="%s" data-telltale-key="%s"></script>' . "\n",
		esc_url( 'https://app.trytelltale.dev/sdk/v1.js' ),
		esc_attr( 'YOUR_SITE_PUBLISHABLE_KEY' )
	);
}, 1 );

The priority 1 prints it early in <head>. The publishable key (ao_pk_...) is meant for the browser. Never put the server key (ao_sk_...) in a theme, a snippet or a page.

The tag records from page load. That is right for sites without a cookie or consent banner.

If your site shows a banner (for example from a cookie consent plugin), hold the tag: add data-telltale-wait-for-consent. A held tag sends nothing at all until you call optIn().

HTML
<script src="https://app.trytelltale.dev/sdk/v1.js" data-telltale-key="YOUR_SITE_PUBLISHABLE_KEY" data-telltale-wait-for-consent></script>

Then, from your consent plugin's "consent given" and "consent withdrawn" hooks or JavaScript events, call:

JavaScript
// When the banner allows measurement:
window.Telltale.getClient().optIn();
// When the visitor refuses or withdraws:
window.Telltale.getClient().optOut();

Apply the saved decision on every page load, and again each time it changes. Signing in is not consent. For OneTrust, Cookiebot or Sourcepoint, use the Consent bridge guide and the OneTrust, Cookiebot or Sourcepoint recipe.

Some consent plugins block scripts until consent by changing their type. If yours does that, do not also add data-telltale-wait-for-consent; pick one way to wait.

Identify the signed-in user

On a membership, shop or learning site, link each session to the WordPress user. Send the user's numeric ID, which is stable and opaque. Never send the e-mail address, username, display name or phone number.

From your server (recommended). Your own backend links the session to the user it authenticated. This is the identity Telltale trusts. See Quickstart step 2 and Server API › Associate identity.

In the tag (a label). With the child-theme install, add the signed-in user's ID to the tag, only when someone is logged in:

php
// wp-content/themes/your-child-theme/functions.php
add_action( 'wp_head', function () {
	$user = '';
	if ( is_user_logged_in() ) {
		$user = sprintf( ' data-telltale-user-id="%s"', esc_attr( 'wp_' . get_current_user_id() ) );
	}
	printf(
		'<script src="%s" data-telltale-key="%s"%s></script>' . "\n",
		esc_url( 'https://app.trytelltale.dev/sdk/v1.js' ),
		esc_attr( 'YOUR_SITE_PUBLISHABLE_KEY' ),
		$user
	);
}, 1 );

If your site has organisations or teams, add data-telltale-account-id the same way with that group's ID. A held tag ignores these attributes until optIn(); after consent, call window.Telltale.getClient().identify({ userId: 'wp_42' }) with the same ID. Calls to identify() reject while the tag is held, so wrap them in try { ... } catch {}.

A full-page caching plugin can serve one visitor's page to another. Make sure logged-in users get uncached pages (most caching plugins do this by default), or the wrong ID could be printed.

Content Security Policy

Most WordPress sites send no Content Security Policy. If yours does (from a security plugin, your host or .htaccess), allow the Telltale server for scripts and for connections:

HTTP
Content-Security-Policy: script-src 'self' https://app.trytelltale.dev; connect-src 'self' https://app.trytelltale.dev

Keep any sources your policy already lists. Never add 'unsafe-inline' or 'unsafe-eval' for Telltale. The Content Security Policy guide has the nonce option too.

Check it worked

  1. In the Telltale dashboard, open Settings › Channels and leave the Is it working? check open.
  2. Choose Open my site to test it, or open your site in a new tab yourself. Browse a page or two.
  3. Watch the check move through Script loaded on your address, First session received and, if you set up identify, Signed-in user linked (log in to your site to see it). When the first session arrives, it links to it.

You can also look in your browser's DevTools › Network: sdk/v1.js should answer 200, and so should api/sdk/init. If it stays at the first step, see It's not working.

Common mistakes