Script Tag Setup

Add A/B testing to any website with a single <script> tag. No npm, no bundler, no build step, and no JavaScript required for visual experiments.

Who this is for

  • Static HTML sites
  • WordPress, Squarespace, Webflow, or any CMS
  • Landing pages and marketing sites
  • Any project where you don't want (or can't use) a build tool

1. Add the SDK (one line)

Paste this in your HTML <head> so the SDK loads before the page renders:

html
<head>
  <!-- other tags... -->
  <script src="https://cdn.softpath.co/sdk/v1/cadence.min.js" data-project="YOUR_PROJECT_ID"></script>
</head>

That's it — one line. The SDK auto-initializes, fetches your experiment config, and runs any visual experiments on the current page.

Get your Project ID

Find your Project ID (like proj_Ax8mK2pQr4nB) on your project Settings page in the CADENCE dashboard, under the Quick Install tab.

2. Zero-code visual experiments

If you create a visual experiment in the dashboard (using the Visual Editor) and set a target URL, CADENCE automatically:

  • Detects when a visitor lands on the matching page
  • Assigns them to a variant
  • Applies the visual changes (text, colors, layout)
  • Tracks the exposure event

No additional code needed on your site.

3. Zero-code conversion tracking

Add data-cadence-goal to any clickable element to track it as a conversion:

html
<button data-cadence-goal="signup-click">Sign Up Free</button>
<a href="/pricing" data-cadence-goal="pricing-visit">See Pricing</a>

When a visitor clicks the element, CADENCE automatically tracks a conversion event with the goal name you specified.

You can also configure conversion rules in the dashboard (under experiment settings) for:

  • URL match — track a conversion when the visitor reaches a specific page (e.g., /thank-you)
  • Click — track a conversion when the visitor clicks a specific CSS selector (e.g., #buy-now-btn)

4. Code-based experiments (advanced)

For experiments that need custom JavaScript logic, add a second <script> block:

html
<script>
  Cadence.ready().then(function () {
    var variant = Cadence.getVariant('cta-button-test')
    var button = document.getElementById('cta-button')

    if (variant === 'blue') {
      button.style.backgroundColor = '#3b82f6'
      button.textContent = 'Start Free Trial'
    } else if (variant === 'green') {
      button.style.backgroundColor = '#16a34a'
      button.textContent = 'Try It Free'
    }
  })
</script>

What this does

  1. Cadence.ready() waits for the SDK to fetch your experiment config
  2. getVariant('cta-button-test') assigns a variant and automatically tracks an exposure
  3. Your code applies the variant's changes to the page

5. Complete example — button color test

Here's a full working HTML page:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My Landing Page</title>
  <script src="https://cdn.softpath.co/sdk/v1/cadence.min.js" data-project="YOUR_PROJECT_ID" data-anti-flicker></script>
  <style>
    .cta-button {
      padding: 16px 32px;
      font-size: 18px;
      font-weight: bold;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      background-color: #1e293b;
    }
  </style>
</head>
<body>

  <h1>Welcome to our site</h1>
  <button id="cta-button" class="cta-button" data-cadence-goal="cta-click">Get Started Free</button>

  <script>
    Cadence.ready().then(function () {
      var variant = Cadence.getVariant('cta-button-test')
      var button = document.getElementById('cta-button')

      if (variant === 'blue') {
        button.style.backgroundColor = '#3b82f6'
        button.textContent = 'Start Free Trial'
      } else if (variant === 'green') {
        button.style.backgroundColor = '#16a34a'
        button.textContent = 'Try It Free'
      }
    })
  </script>

</body>
</html>

Notice: the button has data-cadence-goal="cta-click" — clicks are automatically tracked as conversions without any additional JavaScript.

6. Create the experiment in the dashboard

  1. Go to your project and click Create Experiment
  2. Name it cta-button-test (must match the string in your code exactly)
  3. Add three variants:
    • control — the default dark button
    • blue — blue button with "Start Free Trial"
    • green — green button with "Try It Free"
  4. Set traffic allocation to 100% and split weights evenly (33/33/34)
  5. Start the experiment

7. Track conversions with JavaScript (optional)

Beyond data-cadence-goal, you can track conversions programmatically for more complex scenarios:

html
<script>
  // Form submission
  document.getElementById('contact-form').addEventListener('submit', function () {
    Cadence.trackConversion('form-submit')
  })

  // Page view (e.g., reaching a thank-you page)
  if (window.location.pathname === '/thank-you') {
    Cadence.trackConversion('purchase-complete', { value: 49.99 })
  }
</script>

You can pass an optional properties object as the second argument. Use it for revenue values, plan names, or any metadata you want to see in your results.

8. Identify users (optional)

By default, the SDK generates an anonymous user ID and stores it in localStorage. This means the same visitor gets the same variant every time they return — as long as they don't clear their browser data.

For logged-in users, pass your own user ID for consistent assignment across devices:

html
<script src="https://cdn.softpath.co/sdk/v1/cadence.min.js" data-project="YOUR_PROJECT_ID" data-user-id="user_abc123"></script>

Mix anonymous and logged-in

You can initialize without a userId for anonymous visitors, then re-initialize with a userId after login. The SDK will use the new ID for all future assignments.

9. Prevent flicker

Without anti-flicker, visitors see the original page flash before their variant loads. This is distracting and can bias results. Add data-anti-flicker to prevent it:

html
<script src="https://cdn.softpath.co/sdk/v1/cadence.min.js" data-project="YOUR_PROJECT_ID" data-anti-flicker></script>

The page content is hidden until either:

  • The SDK loads and applies variant changes, or
  • The safety timeout (2 seconds) elapses — whichever comes first

If 2 seconds isn't enough (e.g., slow network), customize the timeout with data-anti-flicker-timeout="3000".

Recommended for all visual experiments

Any experiment that changes what visitors see (colors, text, layout, hiding elements) should use data-anti-flicker. The complete example above already includes it.

10. Multiple experiments on one page

Visual experiments auto-run on matching pages. For code-based experiments, each getVariant() call is independent:

html
<script>
  Cadence.ready().then(function () {
    // Experiment 1: button color
    var btnVariant = Cadence.getVariant('cta-button-test')
    if (btnVariant === 'blue') {
      document.getElementById('cta').style.backgroundColor = '#3b82f6'
    }

    // Experiment 2: headline copy
    var headlineVariant = Cadence.getVariant('hero-headline')
    var headlines = {
      control: 'Build something great',
      urgency: 'Build something great — limited time offer',
      social: 'Join 10,000+ teams building something great',
    }
    document.getElementById('hero-title').textContent =
      headlines[headlineVariant] || headlines.control
  })
</script>

Script tag attributes

| Attribute | What it does | Required | |-----------|-------------|----------| | data-project | Your Project ID | Yes | | data-user-id | Your user's ID for cross-device consistency | No | | data-api-url | Custom API URL (only if self-hosting) | No | | data-anti-flicker | Hide content until visual changes apply | No |

Full method reference

| Method | What it does | |--------|-------------| | Cadence.ready() | Returns a Promise that resolves when config is loaded | | Cadence.getVariant('name') | Get the user's variant (tracks exposure automatically) | | Cadence.runTest({ testId, variants, ... }) | Run a test with declarative config | | Cadence.trackConversion('name', props?) | Track a goal completion | | Cadence.track('name', props?) | Track a custom event | | Cadence.isFeatureEnabled('name') | Check if a feature flag is on | | Cadence.getFeatureValue('name', default) | Get a feature flag's value | | Cadence.enableAntiFlicker(ms) | Hide content until variants apply | | Cadence.destroy() | Flush events and clean up | | Cadence.version | Returns the SDK version string |

For the full API reference with detailed signatures and examples, see API Reference.

Troubleshooting

Variant always returns "control"

Make sure Cadence.ready() has resolved before calling getVariant(). Without it, the SDK hasn't loaded your experiment config yet. Always put your logic inside the .then() callback, or use Cadence.runTest() which handles this automatically.

Events not appearing in the dashboard

Events are batched and sent every 5 seconds. Wait a moment, then refresh. Check your browser's Network tab for requests to /api/sdk/p/[projectId]/events — look for 4xx errors that indicate a bad Project ID.

Flicker on page load

Add data-anti-flicker to the script tag — this hides the page until variant changes are applied. See step 9 above.

Project ID not working

Double-check that you copied the full Project ID from project Settings. It should start with proj_ followed by 12 characters. Go to Settings and click Test Connection to verify.

Content Security Policy (CSP) errors

If your site has a CSP, make sure it allows cdn.softpath.co in script-src and your CADENCE API domain in connect-src.

Next steps