Developer docs

Add the snippet

One script in the theme. A publishable write key — not a secret in git. Until events arrive, Home stays empty on purpose.

The line

html Any HTML theme
<script
  src="https://api.executen.com/sdk/executen.js"
  data-write-key="pk_live_…"
  async
></script>

Auth is the write key. data-workspace is ignored and must never be trusted from the browser. If you omit data-ingestion-url and data-edge-url, the SDK posts to the script origin: /api/collect/track and /api/collect/decide.

AttributeRequiredWhat it does
data-write-keyYesPublishable pk_live_…. Tenant for collect and decide.
data-ingestion-urlNoOverride track URL. Local Fastify only.
data-edge-urlNoOverride decide URL. Local Fastify only.
data-countryNoHint. Ingest may also read CF-IPCountry. Not auth.
data-deviceNoHint. Otherwise the SDK reads the user agent.
data-workspaceNeverIgnored. Do not send a workspace id from the shop.

Shopify

Paste it once in layout/theme.liquid, before </head> or </body>. Async. It should not block first paint. Paid orders still come from the Shopify connection — the snippet is the storefront sensor.

liquid layout/theme.liquid
<script
  src="https://api.executen.com/sdk/executen.js"
  data-write-key="{{ settings.executen_write_key | default: 'pk_live_…' }}"
  async
></script>
{% if customer %}
<script>
  window.addEventListener("load", function () {
    if (window.executen) {
      executen.identify("{{ customer.id }}", { name: {{ customer.first_name | json }} });
    }
  });
</script>
{% endif %}

WooCommerce / WordPress

php Theme footer — not a .org plugin
add_action('wp_footer', function () {
  $key = get_option('executen_write_key', 'pk_live_…');
  echo '<script src="https://api.executen.com/sdk/executen.js" data-write-key="' . esc_attr($key) . '" async></script>';
  if (is_user_logged_in()) {
    $id = (string) get_current_user_id();
    echo '<script>window.addEventListener("load",function(){window.executen&&executen.identify(' . json_encode($id) . ');});</script>';
  }
});

Next.js

tsx App Router — public key only
import Script from "next/script";

export function ExecutenSnippet() {
  return (
    <Script
      src="https://api.executen.com/sdk/executen.js"
      strategy="afterInteractive"
      data-write-key={process.env.NEXT_PUBLIC_EXECUTEN_WRITE_KEY}
    />
  );
}

Google Tag Manager

Custom HTML tag. Fire on All Pages after consent if you use a CMP. Do not put sk_live in GTM.

html GTM Custom HTML
<script>
  (function () {
    var s = document.createElement("script");
    s.src = "https://api.executen.com/sdk/executen.js";
    s.async = true;
    s.setAttribute("data-write-key", "pk_live_…");
    document.head.appendChild(s);
  })();
</script>

The snippet auto-sends Page Viewed and asks decide() as soon as it boots. If analytics must wait for a cookie banner, do not inject the script until the visitor allows it. Calling consent.update after the fact cannot unsend the first page.

js After the visitor allows analytics
// Load the snippet, then:
executen.consent.update({
  analytics: true,
  personalization: true,
  marketing: false
});

CSP

http Allow the collect origin — no unsafe-eval for Executen
Content-Security-Policy:
  script-src 'self' https://api.executen.com;
  connect-src 'self' https://api.executen.com;

Page, track, identifyMarkersWrite keys