Tapper
Search docs...
⌘K
SupportDashboard

Monitoring script

Install the monitoring script on your website to analyze user behavior and identify invalid activity.


The Monitoring script is the core of Tapper's invalid traffic detection. It runs on every page of your website, analyzes visitor behavior in real time, and builds the invalid traffic lists your ad platforms use to exclude invalid traffic.

Installing via a tag manager? Your container must already be live on your website. Both Google Tag Manager and Tealium iQ walk you through that setup when you first create one.

Step 1: Obtain the script

In Tapper, open Setup > Website in the sidebar, then the Monitoring area and its Install script and consent tab. If your workspace has more than one protected entity, pick it first in the switcher under the workspace name. Copy the Monitoring script, then head to your tag manager (Google Tag Manager or Tealium iQ), or to your website's HTML if you are installing manually.

Monitoring Script

Copy the monitoring script from your Tapper dashboard

Step 2: Add the script

1
Create a new tag

Navigate to Tags in your GTM dashboard and click New.

2
Configure the tag

Select Custom HTML as the tag type and paste the copied monitoring script into the HTML field.

3
Set the trigger

Under Triggering, select the built-in trigger Initialization - All Pages so the script fires during the initial loading phase of every page.

4
Save the tag

Name your tag Tapper - Monitoring Script and click Save.

5
Publish

Click Submit, enter a version name and description, then click Publish.

Content security policy

If your website sends a Content-Security-Policy header, the browser refuses anything the policy does not name. The monitoring script then fails silently: nothing errors on your side and Tapper simply receives no traffic. Some platforms enforce a policy by default: Magento 2.4.7 and later enforces one on the checkout page (the rest of a Magento storefront is report-only unless you change it). Add the entries below before you install.

The list

This is the exact list Tapper measures and tests in a real browser. Each line is a directive, a source, whether you need it, and what it serves. The table under it explains each entry.

script-src   https://monitor.tapper.ai       REQUIRED     the SDK itself (bundle.js)
connect-src  https://protect.tapper.ai       REQUIRED     every tRPC call: ping, registerTab, pulse, contentRules, events, fingerprints, conversions
connect-src  https://fingerprint.tapper.ai   REQUIRED     JA4/JA4H network fingerprint probe (GET /fingerprint)
img-src      https://protect.tapper.ai       REQUIRED     /fp/summary session summary on every page hide, and the /e/beacon ad-blocker fallback for events
worker-src   blob:                           REQUIRED     worker-thread fingerprint (wfp: navigator + WebGL seen from a Worker)
connect-src  https://m1.openfpcdn.io         OPTIONAL     FingerprintJS vendor install statistics, about 1 page load in 1,000; no Tapper data
script-src   'unsafe-inline'                 CONDITIONAL  Tapper audiences: the ad-platform snippet served by users.pulse is injected as inline script
script-src   https://www.googletagmanager.com CONDITIONAL Tapper audiences on Google Ads: the snippet's gtag.js loader
EntryNeededWhat breaks without it
script-src https://monitor.tapper.aiRequiredNothing runs. No events, no fingerprints, no conversions.
connect-src https://protect.tapper.aiRequiredEvery call to Tapper is refused. The script loads and records nothing.
connect-src https://fingerprint.tapper.aiRequiredThe network fingerprint is never sent, so a bot signal is lost on every visit.
img-src https://protect.tapper.aiRequiredThe summary sent when a page closes is refused, and so is the fallback that delivers events when an ad blocker stops the normal request.
worker-src blob:RequiredPart of the browser fingerprint (the part read from a Worker) is missing, and your CSP report endpoint receives a violation each time.
connect-src https://m1.openfpcdn.ioOptionalNothing of Tapper's. An anonymous statistics request from a fingerprint library, about 1 page load in 1,000. We recommend you do not add it.
script-src 'unsafe-inline'Only with Tapper audiencesThe audience snippet from your ad platform does not run, so visitors are not added to the audience.
script-src https://www.googletagmanager.comOnly with Google Ads audiencesThe Google Ads snippet's gtag.js loader is refused, so visitors are not added to the audience.

About 'unsafe-inline': it weakens your policy's protection against injected scripts, and browsers ignore it when script-src also has a nonce, a hash or 'strict-dynamic'. On such a policy audiences cannot run, even with the entry added.

The audience entries cover only what Tapper injects. The ad platform's own script then calls its own hosts; follow Google's and Meta's CSP guidance for those. A site that already runs their ad tags already allows them.

Where each entry goes

  • worker-src blob:: if your policy has no worker-src but has child-src, add blob: to child-src. If it has neither, add blob: to script-src, or add a worker-src directive that also keeps the sources your own workers need. Note that blob: in script-src also lets blob: scripts run.
  • script-src entries: if your policy also sets script-src-elem, add them there too.
  • connect-src and img-src: if the directive is missing, the browser uses default-src, so add the host there, or add the directive and repeat your default-src sources in it: a new directive stops default-src from applying, and your own requests would break.
  • Nonce policies with 'strict-dynamic' ignore host lists in script-src. The script then loads only if whatever inserts it is trusted, for example GTM loaded with your nonce.
  • Trusted Types (require-trusted-types-for 'script') is not supported.

Inline code and Google Tag Manager

The list assumes no inline code of Tapper's runs on your page. The monitoring script you copy from the dashboard is an inline <script> block, and so is a GTM Custom HTML tag. Under a policy without 'unsafe-inline' in script-src, the browser refuses that block and the monitoring script is never even requested, whichever hosts you added. Pick one:

  • Recommended: your own script file. Save the body of the snippet from the dashboard (the code between <script> and </script>) as a file on your own site, for example /js/tapper.js, and load it with <script src="/js/tapper.js"></script>. Your policy already allows your own origin ('self'), so nothing to add beyond the list.
  • Nonce (manual HTML install only). Add your per-response nonce to the snippet's <script> tag. A GTM Custom HTML tag cannot carry a per-response nonce.
  • Hash. Add the block's 'sha256-...' hash to script-src. The hash differs for every protected entity and changes if the block is edited at all.

The GTM Community Template is not a route under a strict policy for now: the version the gallery currently serves does not start the monitor. Use your own script file until this page says otherwise.

The Tealium install is not affected: its extension code runs inside utag.js, not as an inline block.

Allowing https://www.googletagmanager.com lets the GTM container load. It does not allow the scripts GTM then injects: each of those still needs its own host in the policy (here https://monitor.tapper.ai), and inline Custom HTML tags need one of the options above.

Example header

Content-Security-Policy: script-src 'self' https://monitor.tapper.ai; connect-src 'self' https://protect.tapper.ai https://fingerprint.tapper.ai; img-src 'self' https://protect.tapper.ai; worker-src 'self' blob:

Merge these sources into your existing directives; do not replace your policy with this line.

Magento

With Magento_Csp, add a etc/csp_whitelist.xml to one of your modules:

<?xml version="1.0"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
    <policies>
        <policy id="script-src">
            <values>
                <value id="tapper-monitor" type="host">https://monitor.tapper.ai</value>
            </values>
        </policy>
        <policy id="connect-src">
            <values>
                <value id="tapper-protect" type="host">https://protect.tapper.ai</value>
                <value id="tapper-fingerprint" type="host">https://fingerprint.tapper.ai</value>
            </values>
        </policy>
        <policy id="img-src">
            <values>
                <value id="tapper-protect-img" type="host">https://protect.tapper.ai</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

Then run bin/magento cache:flush.

  • Worker entry: do not add a worker-src policy. Magento sets no worker-src, and its default child-src already allows blob:, so the worker passes. A worker-src policy would block your store's own workers. If your store removed blob: from child-src, restore the blob scheme under csp/policies/storefront/children/schemes in your config.
  • Inline dashboard snippet: where the policy is enforced, allow the snippet by its hash inside the script-src policy, or use one of the other options above:
<value id="tapper-snippet" type="hash" algorithm="sha256">BASE64_HASH_OF_THE_SNIPPET_BODY</value>
  • Audiences: csp_whitelist.xml accepts only hosts and hashes, so it cannot add 'unsafe-inline'. Magento 2.4.7 and later also turns off inline scripts on the checkout page on purpose, so Tapper audiences cannot run there.

Step 3: Verify

Use GTM's Preview mode to confirm the tag fires correctly across your website.