Skip to main content

JavaScript

Introduction

The Piano Analytics JavaScript SDK is the most popular way to implement data collection on websites. This lightweight library enables you to track user interactions, page views, conversions, and custom events with minimal setup.

What you'll learn in this guide:

  • How to load and configure the JavaScript SDK
  • Different implementation methods
  • Basic and advanced configuration options
  • How to send events and track user behavior

Prerequisites:

  • Basic knowledge of HTML and JavaScript
  • Access to your Piano Analytics site ID and collection domain
  • Ability to modify your website's code
attention

The legacy xtor marketing campaign syntax is no longer recognized. Use "at_" instead.

Load the library

The first step to use our SDK is to load the JS file. You have two ways to do this:

CDN

We offer delivery of our JS SDK on our CDN. You can choose between different implementation approaches:

Standard implementation (≥ 6.16.0)

Our recommended approach combines library loading and configuration in a single, self-contained script:

(function (_config) {
var script = document.createElement("script");
script.src = "https://tag.aticdn.net/piano-analytics.js";
script.async = true;
script.dataset.config = JSON.stringify(_config);
document.head.appendChild(script);
})({
site: 123456789,
collectDomain: "https://xxxxxxx.pa-cd.com",
consentDefaultMode: "opt-in",
});
advantages
  • Single script: No need to manage separate loading and configuration steps
  • Asynchronous loading: Non-blocking script execution
  • Configuration via data attribute: Clean configuration management
note

Replace 123456789 with your site ID and xxxxxxx.pa-cd.com with your collection domain. You can customize any configuration parameters within the _config object.

To use a specific version, replace piano-analytics.js with js-sdk/piano-analytics-<version.number>.js in the script source (≥ 6.16.0).

Traditional script tag

You can also load our SDK using traditional HTML script tags:

<script
type="text/javascript"
src="https://tag.aticdn.net/piano-analytics.js"
></script>

Available files

We offer delivery of every version of our JS SDK on our CDN, the file URL follows this pattern: https://tag.aticdn.net/js-sdk/piano-analytics-<version.number>.js.

You can also load the latest version from https://tag.aticdn.net/piano-analytics.js.

Latest version: 6.18.0
Standard implementation:
(function (_config) {
var script = document.createElement("script");
script.src = "https://tag.aticdn.net/js-sdk/piano-analytics-6.18.0.js";
script.async = true;
script.dataset.config = JSON.stringify(_config);
document.head.appendChild(script);
})({
site: 123456789,
collectDomain: "https://xxxxxxx.pa-cd.com",
consentDefaultMode: "opt-in",
});
Traditional script tag:
<script type="text/javascript" src="https://tag.aticdn.net/js-sdk/piano-analytics-6.18.0.js"></script>

You can find a list of all our JS SDK versions on the GitHub releases page.

Available files

6.18.0

Release date (CDN file):
2026-05-05
CDN URL:
https://tag.aticdn.net/js-sdk/piano-analytics-6.18.0.js
SHA384 SRI checksum:
integrity="sha384-QIOkC7r0xWo/J/PbjqOAAS8H3Lc8KIbOOKaf36oiZkwWpKC/SofEtNlX+88GBmif"
Source code:

6.17.1

Release date (CDN file):
2026-05-05
CDN URL:
https://tag.aticdn.net/js-sdk/piano-analytics-6.17.1.js
SHA384 SRI checksum:
integrity="sha384-gpmdaEaw46zmf6BOVonMShB5XOQT7V/te2r+ffTpLFGPe+y6QSzSXeb52+LTP9+6"
Source code:

6.17.0

Release date (CDN file):
2026-01-19
CDN URL:
https://tag.aticdn.net/js-sdk/piano-analytics-6.17.0.js
SHA384 SRI checksum:
integrity="sha384-vLmChHJVXxcl/Emd2dCu+ol0482rB3EFX1escCBS25RTUd04lU12OeYzHKKIwkwO"
Source code:
View all available files →
attention

Using the latest version file (piano-analytics.js) will automatically upgrade the SDK when new releases ship. If you need control over the version in use, use a versioned file instead.

Download

You can also download the file from GitHub and host it on your own server or CDN.

Configuration

In order to set up your tracking, you need to set the configuration of the library.

To do this, we offer two configuration methods depending on what you want to set up.

Basic configuration

pa.setConfiguration(configurationKey, configurationValue);

// or

pa.setConfigurations(configurationObject);

Here is the minimal configuration required:

try {
// Basic configuration method
pa.setConfiguration("site", 123456789); // your site id
pa.setConfiguration("collectDomain", "https://<xxxxxxx>.pa-cd.com"); // your collection domain

// or bulk configuration (recommended)
pa.setConfigurations({
site: 123456789,
collectDomain: "https://<xxxxxxx>.pa-cd.com",
});
} catch (error) {
console.error("Piano Analytics configuration error:", error);
// Handle configuration failure gracefully
}
note

Don't hesitate to read our collection methods article to find the collection domain that has been assigned to you.

You can also use a custom domain thanks to our CDDC.

Here are the available configurations:

CategoryNameDescriptionTypeValueMore info
GlobalcollectDomainCollection domainstring"https://<xxxxxxx>.pa-cd.com"View
GlobalsiteSite idint123456789View
GlobalpathRequest pathstring"event"
GlobaladdEventURLAutomatically adds a event_url_full property to all events, containing the URL of the current page. Was page_url on < 6.10.0string"false", "withoutQS" (default), "true"
GlobalsendEmptyProperties≥ 6.9.0 Allow sending properties with an empty value (empty string or undefined)booleantrue (default), false
GlobaluseSendBeacon≥ 6.16.0 Allow using sendBeacon browser API to send events. Use fetch if falsebooleantrue, false (default since 6.18.0)
GlobalenableAutomaticPageRefresh≥ 6.12.0 Allow the SDK to automatically manage page context refreshbooleantrue (default), falseView
PrivacysendEventWhenOptoutWhether to send events when the user has opted outbooleantrue (default), false
CampaigncampaignPrefixChoose with an order of priority the type of campaign to be collectedarray["at_"]View
CampaignenableUTMTrackingUTM parameters collected as propertiesbooleantrue (default), falseView
GlobalallowHighEntropyClientHints≥ 6.9.0 Allow retrieving of high entropy client hintsbooleantrue (default), falseView

SDK configuration

This method runs asynchronously and overrides the SDK configuration.

You have to define it before SDK's loading.

window._pac = window._pac || {};

<script
type="text/javascript"
src="https://tag.aticdn.net/piano-analytics.js"
></script>;
tip

We recommend setting the configuration within the <head> of your page.

Here is an example of what you can configure:

window._pac = window._pac || {};
_pac.cookieDomain = ".mysite.com";
_pac.path = "event";

<script
type="text/javascript"
src="https://tag.aticdn.net/piano-analytics.js"
></script>;

These configurations must be set before loading the SDK:

CategoryNameDescriptionTypeValueMore info
GlobalcookieDomainCookie domainstring"mysite.com" (current domain by default)
GlobalcookieSameSiteSameSite attribute for client-side cookiesstring"lax" (default), "none", "strict"
GlobalcookieSecureSecure attribute for client-side cookiesbooleantrue (default), false
GlobalencodeStorageBase64Whether storage values are Base64-encodedbooleantrue, false (default)
GlobalqueueVarName≥ 6.4.0 Variable name used for queuingstring"_paq" (default)View
GlobalglobalVarName≥ 6.12.0 Variable name used for global instancestring"pa" (default)
PrivacyprivacyDefaultModePrivacy mode by defaultstring"optin" (default)View
PrivacyenableExtendedOptout≥ 6.13.0 Enable extended opt-out featurebooleanfalse (default)View
StoragestorageLifetimePrivacyLifetime Storage Privacy valueint395 (days)View
StoragestorageLifetimeUserLifetime Storage User valueint395 (days)View
StoragestorageLifetimeVisitorLifetime Storage Visitor valueint395 (days)View
StoragevisitorStorageModeRelative or fixed cookie lifetime value for visitorstring"fixed" (default), "relative"
Visitor PolicyisVisitorClientSideWhether the cookie is set client-side. If false, server-sidebooleantrue (default), false
note

All configurations in "Basic configuration" are compatible with "SDK configuration" method.

Asynchronous tagging

The object _paq can be used to push commands in a queue, executed as soon as the tracker is loaded.

Each command is represented by an array pushed to the queue:

_paq.push([command, (... args)]);

The first element of the array represents the tracker's method to call (e.g.: sendEvent, setProperty, setUser...). The following elements are the method's arguments.

Example:

let _paq = window._paq || [];

try {
_paq.push(["setUser", "ID18859", "Premium user", true]);
_paq.push(["sendEvent", "page.display", { page: "homepage" }]);
} catch (error) {
console.error("Piano Analytics error:", error);
}
note

In some cases, you could need to change the name of the variable used for queuing asynchronous calls (e.g.: Matomo conflict). This can be changed thanks to the configuration key queueVarName.

window._pac = window._pac || {};
_pac.queueVarName = '_paqueue'; // set the queue variable name

window._paqueue = window._paqueue || [];
_paqueue.push(['sendEvent', 'page.display', {"page": "homepage", ...}]);

Piano Cross-product integration

Since v6.7.0, PA JS SDK integrates native synchronization with other Piano products SDKs.

This includes automatic retrieval of a common visitor ID, pageview ID, user access, and content properties.

SPA

In order to refresh the pageview_id in your SPA, you can call the method pa.refresh() to regenerate the page context.

Automatic page context management

Since version 6.12.0, the SDK automatically refreshes the page context when a second page.display event is sent on the same instance (configuration enableAutomaticPageRefresh: true by default).

Only one of both (pa.refresh() or automatic detection) is possible for an implementation. Only the first one encountered on an instance will be available for the lifetime of the instance.

Content properties

Since 6.7.0, the SDK automatically sends content properties from HTML markup. Please check this page for expected markup.

In order to set the content properties, you can either do it through Composer implementation, or through PA SDK:

// set one content property
pa.setContentProperty("type", "article");
// -> content_type = 'article'

// or set multiple properties at once
pa.setContentProperties({
type: "article",
publication_date: 1669109350,
});
// -> content_type = 'article'
// -> content_publication_date = 1669109350
note

When using these methods, content_ prefix is automatically added to the property key.

Content Security Policy (CSP)

Configure your CSP settings:
SDK loading source

The following directives are needed in the CSP to use this setup:

script-src: 'unsafe-inline' https://tag.aticdn.net
connect-src: https://xxxxxxx.pa-cd.com

Changelog

You can find the JavaScript changelog directly on GitHub.

info

If you want to stay updated with our SDK releases, subscribe on GitHub:

Subscribe to GitHub releases