Envie
Guides

Events & analytics glue

Every wishlist interaction emits a DOM event — forward them to your analytics stack in a few lines.

This page lists every event the components emit and shows how to wire them into GA4, a data layer, or any tracker.

The events

All events bubble and cross shadow-DOM boundaries (composed), so one listener on document catches everything. Payloads are on event.detail.

EventFired bydetail
envie:readythe store, on document{ count, config, list } — first load complete, once per page
envie:addedenvie-button{ productId, variantId, handle, count }
envie:removedenvie-button{ productId, variantId, handle, count }
envie:mergedthe client, on documentthe merged list — a guest list just became the customer's
envie:sharedenvie-share{ shareToken, url }
envie:renderedenvie-list{ count } — items currently rendered
envie:errorany component{ message } — the optimistic update was reverted

Forward to a data layer

Complete, paste-ready — works with GTM's dataLayer and adapts to anything else:

<script>
	window.dataLayer = window.dataLayer || [];

	["envie:added", "envie:removed"].forEach(function (type) {
		document.addEventListener(type, function (event) {
			window.dataLayer.push({
				event: type === "envie:added" ? "add_to_wishlist" : "remove_from_wishlist",
				product_id: event.detail.productId,
				variant_id: event.detail.variantId,
				product_handle: event.detail.handle,
				wishlist_count: event.detail.count,
			});
		});
	});
</script>

In a Liquid theme this goes in theme.liquid (or a custom-code block). In a headless app, register the same listeners wherever you bootstrap analytics.

GA4 directly

document.addEventListener("envie:added", (event) => {
	gtag("event", "add_to_wishlist", {
		items: [{ item_id: event.detail.productId, item_variant: event.detail.variantId ?? undefined }],
	});
});

Headless: subscribe to state instead

If you use @getenvie/client without the components, the reactive snapshot is often more convenient than events:

import { createEnvie } from "@getenvie/client";

const envie = createEnvie({
	mode: "public",
	shop: "your-store.myshopify.com",
	publicKey: "env_pk_your_store_xxxxxxxx",
});

const unsubscribe = envie.subscribe((state) => {
	// { ready, count, items, config } — fires on every change
	console.log("wishlist count:", state.count);
});

Server-side events

DOM events cover the browser. For your backend — sync, notifications, a CDP — use outbound webhooks: the same interactions delivered to your endpoint, signed, with retries.

Common mistakes

  • Listening on the element instead of document. Auto-injected buttons appear after your script runs; a delegated listener on document catches them all, whenever they arrive.
  • Counting envie:added as a conversion event by itself. The event fires after the server confirms, but a shopper can toggle rapidly — dedupe by productId in your pipeline if your numbers must be exact.

On this page