Embed

Integration Guide

API Reference
Embed an Activoice campaign on any website in minutes

The Activoice embed lets you add a campaign widget directly on your own website. Visitors can participate in the campaign without ever leaving your page — all you need is a small snippet of HTML.

How it works

The embed loads your campaign inside an <iframe>. By default, it measures the first screen, keeps that height (at least 600 px), and scrolls longer content inside the iframe. A lightweight JavaScript loader (loader.js) shows a spinner while the campaign initializes, then reveals the sized iframe. The host page's query string is passed to the embed, so personalized links from the Share panel also work on a page that embeds the campaign.

Quick start

Add the loader script

Paste the following tag inside the <head> of your page. You will find the exact URL in your Activoice admin, in the campaign's Share panel, Embed tab.

<head>
  <script src="https://app.activoice.org/embed/v1/loader.js"></script>
</head>

Add a container

Place an empty <div> wherever you want the campaign to appear:

<div id="av-embed-container"></div>

Initialize the embed

Call Activoice.init() with your campaign ID:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
})
</script>

That's it. This minimal snippet is the recommended integration: its defaults are designed to blend into your page, and the options described further down only matter when your site's design calls for them. The complete snippet looks like this:

index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://app.activoice.org/embed/v1/loader.js"></script>
</head>
<body>
  <div id="av-embed-container"></div>

  <script>
  window.Activoice.init({
    container: '#av-embed-container',
    campaignId: 'my-campaign-slug',
  })
  </script>
</body>
</html>
Copy-paste ready snippets are available directly from your Activoice admin: open a campaign, then click Embed in the top-right actions menu.
Using an AI assistant connected to Activoice? Ask it to embed a campaign on your site: it reads this guide and writes the snippet with the right campaign id for you.

Customizing the spinner color

By default the loading spinner uses Activoice's brand yellow (#fed13a). Match it to your site's colors with embedOptions.spinnerColor:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    spinnerColor: '#0057ff',
  },
})
</script>

Choosing where to start the campaign flow

By default, visitors land directly on the action steps (the "go" page). If your campaign has a dedicated landing page you want to show first, set initialPage to 'landing':

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    initialPage: 'landing',
  },
})
</script>
ValueBehavior
'steps' (default)Opens directly on the action step
'landing'Shows the campaign landing page first

Controlling the iframe height

Start with no height options. The default displayMode: 'fixedHeight' and height: 'auto' measure the first screen after applying the campaign configuration and theme, then freeze the iframe height at a minimum of 600 px. Later steps and generated content scroll inside that frame. The width remains responsive; changing the width does not recalculate the frozen height. Call Activoice.init() again to take a new measurement.

Initialization waits up to two seconds for custom CSS imports, the first screen's fonts and content images. Resources that arrive later use the internal scroll area. A long first screen produces a tall iframe: automatic height has no maximum.

For a specific height, set height directly. You do not need to size the container:

<div id="av-embed-container"></div>

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    height: '700px',
  },
})
</script>

To fill an existing panel, use height: '100%' and give its container a definite height:

<div id="av-embed-container" style="height: 80vh;"></div>

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    height: '100%',
  },
})
</script>
Display modeHeightBehavior
'fixedHeight' (default)'auto' (default)Freezes the initial content height, at least 600 px, with internal scrolling
'fixedHeight''100%'Fills the sized container and follows changes to its height, with internal scrolling
'fixedHeight'e.g. '700px'Uses that exact height, with internal scrolling
'inline'IgnoredUpdates the iframe height whenever its content resizes

The 600 px minimum applies only to automatic height. Explicit pixel heights and 100% keep the height you request.

To let the embed grow and shrink with every step, set embedOptions: { displayMode: 'inline' }.

fullHeight is no longer a supported mode. Replace it with height: '100%' to retain the container-based layout. Unknown display modes fall back to fixedHeight + auto, ignoring any supplied height. Existing snippets without a display mode now use the frozen automatic height; explicitly set inline to keep continuous resizing.

Control UI appearance

These flags control visible UI elements inside the embedded campaign. They all default to false, which gives the cleanest integration; enable one only when your page needs it, for example the campaign's own background on a page whose colors clash with it:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    withBackground: true,
  },
})
</script>
OptionDefaultEffect
withToolbarfalseShows the navigation toolbar (back button, step indicator)
withBackgroundfalseApplies the campaign's background color to the iframe
withPaddingfalseAdds horizontal padding to the content area
Enable all three only when you want the embed to look like the standalone campaign page rather than a part of your site.
When withBackground is enabled and the campaign's background color is dark, text and UI elements automatically switch to a light color so content stays readable — no extra configuration needed.

Matching the host page design

The embed renders with your organization's design: the colors and custom CSS of your Activoice admin, made for your website. On a page that is not your website, such as a partner site or a campaign microsite, override them in campaignOverrides rather than changing them in the admin, which would change every campaign page:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  embedOptions: {
    spinnerColor: '#0057ff',
  },
  campaignOverrides: {
    color_background: '#0b1a33',
    color_main: '#0057ff',
    color_buttons: '#ff6b00',
    custom_css: '',
  },
})
</script>
FieldEffect
color_backgroundColor of the surface the embed sits on. Text and derived surfaces adapt to it; the embed paints it only with withBackground: true.
color_mainBrand color of the campaign pages: landing gradient, toolbar, links and focus states.
color_buttonsColor of the call-to-action buttons; their label color is picked for contrast.
custom_cssReplaces the organization's custom CSS. '' removes it, the right choice unless you have a CSS written for Activoice pages.

A field you omit keeps the organization's value. Colors are #rrggbb values; anything else is ignored with a warning in the browser console. The CSS is checked before it is applied: no external URL, @import of Google Fonts stylesheets only, 50 000 characters at most; a rejected CSS is dropped with a warning. Set embedOptions.spinnerColor to the brand color so the loading spinner matches.

Write custom_css from the custom CSS template: a complete stylesheet for an example brand, one block per part of the campaign flow, whose comments say what to edit and what to keep. Edit its values, delete the blocks you do not need, and never add a selector of your own: the template is all you need to know about the Activoice pages, and it follows the three colors through var(--color-primary), var(--color-secondary) and var(--color-fg).

On a dark page, set color_background to the page color: text turns light while the background stays transparent. Add withBackground: true to paint it inside the embed too.

Embedding multiple campaigns on the same page

Call Activoice.init() once per container. Each embed is independent:

<div id="campaign-a"></div>
<div id="campaign-b"></div>

<script>
window.Activoice.init({
  container: '#campaign-a',
  campaignId: 'climate-action',
})

window.Activoice.init({
  container: '#campaign-b',
  campaignId: 'housing-rights',
})
</script>

Overriding campaign recipients

campaignOverrides lets you replace the recipients defined in your Activoice admin with your own data. This is useful when recipient data comes from an external CRM or changes dynamically.

Global recipients override

Set recipients at the root of campaignOverrides to apply the same recipients to all interpellations at once:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  campaignOverrides: {
    recipients: [
      {
        first_name: 'Alice',
        last_name: 'Smith',
        email: 'alice.smith@example.com',
        display_title: 'Minister of Ecological Transition',
      },
      {
        first_name: 'Bob',
        last_name: 'Jones',
        email: 'bob.jones@example.com',
        display_title: 'Secretary of State for Housing',
      },
    ],
  },
})
</script>

Per-interpellation recipients override

Target a specific interpellation by its ID to override only its recipients. Per-interpellation overrides take priority over the root-level recipients:

<script>
window.Activoice.init({
  container: '#av-embed-container',
  campaignId: 'my-campaign-slug',
  campaignOverrides: {
    recipients: [
      { first_name: 'Alice', last_name: 'Smith', email: 'alice@example.com' },
    ],
    interpellations: [
      {
        id: 'interpellation-uuid',
        recipients: [
          {
            first_name: 'Charlie',
            last_name: 'Durand',
            email: 'charlie.durand@example.com',
            display_title: 'Deputy Mayor',
          },
        ],
      },
    ],
  },
})
</script>

In this example, the interpellation with ID 'interpellation-uuid' receives Charlie as its recipient, while all other interpellations receive Alice.

See the API Reference for the full list of recipient fields and the resolution order.

Copyright © 2026