VoidhashDocs
DocumentationAPI reference
Dashboard
Get started
Introduction
Quickstart
Setup
Setup overview
Create a project
Products and perks
Paywall locations
CLI
Paywall components
Components
Develop a component
Editor panels
Component definition
Publishing
Installing and capabilities
SDKs
Swift
Kotlin
React Native
Web
Store setup
Connect the App Store
Connect Google Play
Connect Stripe
API libraries
Node.js
PHP
Rust
Go
Resources
MCP server
Ad measurement
Meta ads
Migrate in observer mode
Delete a person's data
Web SDK
Web quickstart
Script tag
Identify users
Track events
Privacy and consent
Page views and attribution
Stripe revenue
Web-to-app handoff
First-party proxy
Tracking domain
Feature flags
Troubleshooting

Script tag

Add Voidhash to a site without a JavaScript build, such as Webflow, WordPress, or plain HTML.

For a site without a bundler, the SDK also ships as one file, voidhash.global.js, that a <script> tag loads from Voidhash's CDN. It contains everything it needs, about 37 kB gzipped, and does what the npm package does: page views, campaign attribution, events, identity, and consent.

Add the snippet

Put both tags in the <head> of every page:

<script>
  window.voidhash = window.voidhash || { q: [] };
  [
    "track",
    "page",
    "identify",
    "signOut",
    "reset",
    "setAnalyticsConsent",
    "setPersonAttributes",
    "on",
  ].forEach(function (method) {
    window.voidhash[method] =
      window.voidhash[method] ||
      function () {
        window.voidhash.q.push([method, arguments]);
      };
  });
</script>
<script
  async
  src="https://cdn.voidhash.com/web/latest/voidhash.global.js"
  data-publishable-key="vh_pk_…"
></script>

The first tag lets the page call window.voidhash before the file has loaded: it keeps the calls. The second loads the SDK without holding up the page. When it arrives, it creates the client as window.voidhash, starts it, records the page view and the campaign the visitor came from, and then makes the kept calls, in order.

Choose a version

/web/latest/voidhash.global.js is always the newest release; your site picks up a new one within minutes of it. To decide when your site updates, load a version instead. A version's file never changes, so add its integrity hash, and the browser refuses to run anything else:

<script
  async
  src="https://cdn.voidhash.com/web/0.0.1-alpha.1-g83f7412/voidhash.global.js"
  integrity="sha384-…"
  crossorigin="anonymous"
  data-publishable-key="vh_pk_…"
></script>

The first line of every file names its version, so the newest one is:

curl -s https://cdn.voidhash.com/web/latest/voidhash.global.js | head -n 1
# /*! @voidhash/web 0.0.1-alpha.1-g83f7412 | MIT */

and the integrity hash of a version is:

curl -s https://cdn.voidhash.com/web/0.0.1-alpha.1-g83f7412/voidhash.global.js | openssl dgst -sha384 -binary | openssl base64 -A

You can also serve the file yourself: install the package as in the quickstart and copy dist/voidhash.global.js from it to your static files.

Options

The tag's data- attributes set the client's options:

AttributeOption
data-publishable-keypublishableKey. Required: without it, the file starts no client.
data-base-urlbaseUrl, for a first-party proxy or a tracking domain.
data-analytics-consentanalyticsConsent: granted, denied, or pending.
data-store-before-consent"false" sets storeBeforeConsent: false.
data-capture-page-views"false" turns off automatic page views.

For any other option, leave data-publishable-key out and create the client yourself once the file has loaded:

<script src="https://cdn.voidhash.com/web/latest/voidhash.global.js"></script>
<script>
  window.voidhash = Voidhash.createVoidhashClient({
    publishableKey: "vh_pk_…",
    featureFlags: { prefetchOnInit: true },
  });
  window.voidhash.initialize();
</script>

Track events and identify visitors

Call the client from anywhere on the page, for example from a button:

<button onclick="voidhash.track('trial_started', { plan: 'pro' })">Start your free trial</button>

After a visitor signs up or signs in, identify them with your user ID:

voidhash.identify("user_42", { email: "ada@example.com" });

Before the file has loaded, only the methods the snippet lists are available. Methods that return a value, such as getDistinctId() for Stripe purchases, work once the client has started:

voidhash.on("initialized", function (event) {
  document.querySelector("#checkout").dataset.visitor = event.distinctId;
});

Ask for consent

Where your site needs consent first, as in the EU, start the client with consent pending and keep its state off the device until the visitor agrees, then pass the answer from your consent tool:

<script
  async
  src="https://cdn.voidhash.com/web/latest/voidhash.global.js"
  data-publishable-key="vh_pk_…"
  data-analytics-consent="pending"
  data-store-before-consent="false"
></script>
// In your consent tool's callback. Calls made before the file loads are kept.
voidhash.setAnalyticsConsent(analyticsAllowed ? "granted" : "denied");

Privacy and consent explains what each answer changes.

Content Security Policy

Besides the connect-src entries in Content Security Policy, allow https://cdn.voidhash.com, or the origin you serve the file from, in script-src. The inline snippet needs a nonce or a hash in script-src, or move it into a file of its own.

PreviousWeb quickstartNextIdentify users

On this page

Add the snippetChoose a versionOptionsTrack events and identify visitorsAsk for consentContent Security Policy