Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.getzenstep.com/llms.txt

Use this file to discover all available pages before exploring further.

Basic installation

Add the <script> tag before </body> on every page:
<script
  async
  src="https://cdn.getzenstep.com/v1/snippet.js"
  data-zenstep="YOUR_SNIPPET_KEY"
></script>

Calling identify

Because the snippet loads asynchronously, call identify() with a guard:
// Safe to call at any point — queued if snippet hasn't loaded yet
if (window.zenstep) {
  window.zenstep.identify("user_123", {
    email: "ada@example.com",
    plan: "grow",
    role: "admin",
  });
} else {
  // Pre-init queue — Zenstep replays these on load
  window.zenstep = window.zenstep || { _q: [] };
  window.zenstep._q.push(["identify", ["user_123", { plan: "grow" }]]);
}
In practice, you can call window.zenstep.identify() directly — the queue captures it automatically before the snippet has loaded:
// This works even before the snippet has loaded
window.zenstep = window.zenstep || { _q: [] };
window.zenstep.identify =
  window.zenstep.identify ||
  function (...args) {
    window.zenstep._q.push(["identify", args]);
  };

window.zenstep.identify("user_123", { plan: "grow" });

jQuery example

If you’re using jQuery and identifying the user on document ready:
$(document).ready(function () {
  var userId = $("#app").data("user-id");
  var userPlan = $("#app").data("user-plan");

  if (userId) {
    window.zenstep?.identify(userId, { plan: userPlan });
  }
});

Multi-page applications

For traditional server-rendered apps (PHP, Rails, Django, etc.), add the snippet in your base layout template and call identify() on every page after the authenticated user is available.
base_layout.html (example)
<!-- In <head> or just before </body> -->
<script
  async
  src="https://cdn.getzenstep.com/v1/snippet.js"
  data-zenstep="{{ ZENSTEP_SNIPPET_KEY }}"
></script>

{% if user.is_authenticated %}
<script>
  window.zenstep?.identify("{{ user.id }}", {
    email: "{{ user.email }}",
    plan: "{{ user.plan }}",
  });
</script>
{% endif %}
Render user data server-side into a <script> block only if you trust the output escaping of your template engine. Never inject unsanitised user input into JavaScript.

Verifying installation

Open the browser console. After the snippet loads you’ll see:
[Zenstep] Loaded N flow(s)
If there are no published flows, you’ll see no message — that’s expected. Check the Install page in the dashboard for a “Snippet detected” confirmation.