Tip: you don't have to write the code yourself. Open your event in the EventSquare admin, go to Settings › Integrations and, next to Website integration, click Instructions. You'll find the code there, already filled in for your ticket shop, with the Copy code button.
Quick start
Paste this code where the ticket shop should appear:
<div id="eventsquare-store"></div>
<script>
window.EventSquare =
window.EventSquare ||
function () {
(EventSquare.q = EventSquare.q || []).push(arguments);
};
EventSquare("init", {
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
});
</script>
<script src="https://yourevent.eventsquare.store/embed/v1.js" async></script>
That's it. Replace the store URL with the link to your own shop (you'll find it in the admin).
What this code does:
The
<div>marks the spot on your page where the shop appears.The first
<script>sets up the shop. It can run before the EventSquare script has loaded: the calls are queued and run afterwards.The last
<script>loads the EventSquare embed script. Because ofasync, it never slows down your page.
HTML-only embed (website builders)
Some website builders (WordPress page builders, Wix, Squarespace, …) don't allow inline JavaScript, or remove it. In that case, use this version, without JavaScript configuration:
<div data-eventsquare-store="https://yourevent.eventsquare.store/en/edition/channel"></div>
<script src="https://yourevent.eventsquare.store/embed/v1.js" async></script>
You set options with data- attributes:
<div
data-eventsquare-store="https://yourevent.eventsquare.store/en/edition/channel"
data-background="opaque"
data-scroll-offset="80"
data-title="Tickets for my festival"
></div>
Options
Option | Data attribute | Default | Description |
|
| — | Required. The URL of your ticket shop. |
| — | — | Required (JavaScript embed). CSS selector or element the shop goes into, e.g. |
|
|
|
|
|
|
| Space in pixels above the shop when it scrolls into view (see Scrolling). Set this to the height of your fixed (sticky) header. |
| — |
| Height in pixels kept free while the shop loads, and the smallest height the shop gets. |
|
|
| Title of the embedded frame, read out by screen readers. |
|
|
|
|
|
|
| After the order: |
|
|
|
|
Language
The language is part of the shop URL: https://yourevent.eventsquare.store/en/... (English), /nl/... (Dutch), /fr/... (French). If you leave out the language (https://yourevent.eventsquare.store/edition/channel), the shop uses the language of your visitor's browser.
Do you have a multilingual website? Then use the shop URL in the matching language on each language version of your page.
Layout and styling
The shop always fills 100% of the width of its container. To limit the width, give the container a
widthormax-width:<div id="eventsquare-store" style="max-width: 800px; margin: 0 auto"></div>
The height is automatic. Don't give the container a fixed
height.The shop has rounded corners and its own styling, and uses the theme color you set in the EventSquare admin. You don't need extra CSS.
On dark backgrounds or photos, use
background: 'opaque'so all text stays readable.
Scrolling
When a visitor goes to the next step (for example from Tickets to Shopping cart) and the top of the shop is out of view, your page smoothly scrolls the shop back into view. If your website has a fixed (sticky) header, set scrollOffset to its height so the shop doesn't disappear behind it:
EventSquare("init", {
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
scrollOffset: 80, // height of your sticky header in px
});
Checkout and payment
The whole ticket purchase happens in the embedded shop, and visitors stay on your website:
Visitors choose their tickets and fill in their details in the embedded shop.
Only the payment itself opens in a small popup window, because banks and payment providers don't allow payments in embedded frames. Meanwhile, the shop shows a message with a button to reopen the payment window, in case it was closed. If the popup is blocked (for example in some in-app browsers), the payment opens in the full browser window.
Free orders and invitations don't need a payment, so there is no popup.
After the order, the shop shows a thank-you message with a button that opens the tickets in a new window. Visitors also receive their tickets by email.
After the order
Choose what happens after the order with the tickets option (or data-tickets):
| What visitors see |
| A thank-you message with a button that opens the tickets in a new window. |
| The tickets right away, in the embedded shop. |
| Nothing from EventSquare: the embedded shop disappears and you show your own confirmation with the |
EventSquare("init", {
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
tickets: "redirect", // or 'none'
});
Your own confirmation with tickets: 'none':
// Listen first, then init (see "Setting up listeners" under Events)
EventSquare("on", "tickets", function (order) {
// The embedded shop has hidden itself: show your own message
var link = document.createElement("a");
link.href = order.url;
link.target = "_blank";
link.textContent = "Download your tickets";
document
.getElementById("eventsquare-store")
.replaceChildren(
"Thank you for your order " + order.transaction_id + "! ",
link,
);
});
EventSquare("init", {
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
tickets: "none",
});
Visitors always receive their tickets by email as well.
Events (for developers)
Listen to what happens in the shop, for example to show a message or keep statistics.
Event | Data | When |
| — | The shop has loaded. |
|
| The height of the shop changed (in px). |
|
| The visitor went to another step or page in the shop. |
| see Tracking events | Tickets were added to the cart. |
| see Tracking events | Tickets were removed from the cart. |
| see Tracking events | The visitor started the checkout (once per cart). |
| see Purchase event | An order was completed (paid, free or invitation). |
| see Tickets event | The tickets of the completed order are ready. |
Callbacks receive (data, instance). Events never contain personal data of your visitors (no names, email addresses or other customer details).
Setting up listeners
Add your listeners before EventSquare('init', …), in the same script, right after the first line (the loader). The loader queues every call until the embed script has loaded and then runs them in order. That way your listeners are ready before the shop starts and you don't miss a single event:
<div id="eventsquare-store"></div>
<script>
// 1. Loader: always first
window.EventSquare =
window.EventSquare ||
function () {
(EventSquare.q = EventSquare.q || []).push(arguments);
};
// 2. Listeners
EventSquare("on", "ready", function () {
console.log("The ticket shop has loaded");
});
EventSquare("on", "navigate", function (event) {
console.log("Visitor went to", event.path);
});
// 3. The shop
EventSquare("init", {
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
});
</script>
<script src="https://yourevent.eventsquare.store/embed/v1.js" async></script>
EventSquare('on', …)listens to all shops on the page, including shops embedded withdata-eventsquare-store: in that case, put the loader and your listeners in a script before the embed script.Using a tag manager or a separate script? Make sure it runs the loader line itself (running it more than once is fine) and adds the listeners before the shop can be used. Events that happened before a listener was added are not repeated, except
ready: areadylistener added later is still called.The examples below leave out the loader and
initto keep them short.
Tracking events
The shop reports the same steps that EventSquare sends to Google Analytics, Meta and TikTok when you connect them in the EventSquare admin. This lets you measure them with your own tags on your website (see Tracking and cookie consent for why):
Event | Google Analytics 4 | Meta Pixel | TikTok Pixel | Sent by |
|
|
|
| Shop |
|
| — | — | Shop |
|
|
|
| Checkout (inline) |
|
|
|
| Checkout (inline) |
All tracking events use the fields of the Google Analytics 4 e-commerce events: currency, value (the total of the change, the cart or the order), items (see Purchase event), plus event, edition and channel. begin_checkout and purchase are only sent when the checkout happens in the embedded shop (checkout: 'inline', the default).
Here's how to forward them all at once:
var metaEvents = {
add_to_cart: 'AddToCart',
begin_checkout: 'InitiateCheckout',
purchase: 'Purchase'
};
var tiktokEvents = {
add_to_cart: 'AddToCart',
begin_checkout: 'InitiateCheckout',
purchase: 'Purchase'
};
['add_to_cart', 'remove_from_cart', 'begin_checkout', 'purchase'].forEach(function(name) {
EventSquare('on', name, function(data) {
// Google Tag Manager: clear the previous ecommerce object first (recommended by Google)
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null, eventsquare: null });
window.dataLayer.push({
event: name,
ecommerce: {
transaction_id: data.transaction_id,
value: data.value,
currency: data.currency,
items: data.items
},
eventsquare: {
event_id: data.event_id,
order_id: data.order_id,
test: data.test === true,
event: data.event,
edition: data.edition,
channel: data.channel
}
});
// Or Google Analytics 4 (gtag.js)
// gtag(\'event\', name, data);
var summary = {
value: data.value,
currency: data.currency,
content_ids: data.items.map(function(item) {
return item.item_id;
}),
content_type: 'product',
};
if (window.fbq && metaEvents[name]) {
// eventID: lets Meta combine it with the same purchase from EventSquare's Conversions API (no double counting)
fbq('track', metaEvents[name], summary, name === 'purchase' ? {
eventID: data.event_id
} : undefined);
}
if (window.ttq && tiktokEvents[name]) ttq.track(tiktokEvents[name], summary);
});
});
Tracking and cookie consent
By default (tracking: 'host'), the embedded shop and checkout run no tracking of their own: not the Google Analytics, Google Tag Manager, Meta Pixel, TikTok Pixel or conversion tag you connected in the EventSquare admin, and not EventSquare's own statistics either. Instead, your page receives the tracking events and passes them on to your tags. Most embedded checkouts work this way, because:
Cookie consent: your cookie banner only applies to your own page. Tags in the embedded shop would run without your visitor's consent; tags on your page follow that consent, like the rest of your website.
Reliable measurement: browsers (Safari, Firefox, and Chrome with privacy settings) block or separate cookies in embedded frames, so tags there lose track of your visitors. Tags on your page don't.
Attribution: ad click IDs and UTM tags (
gclid,fbclid,utm_…) are in your page's address, where your tags can see them.No double counting: each conversion is counted once, by your tags.
Do you still want to use the integrations from the EventSquare admin in the embedded shop? Then set tracking: 'frame' (or data-tracking="frame"). In that case, don't also forward the same events from your page to the same pixels, or deduplicate them (e.g. with Meta's eventID), so conversions aren't counted twice.
Visitors who open your shop directly (not embedded), and older embed codes without the embed script, use the integrations from the EventSquare admin as before. With checkout: 'window', the checkout itself opens in the full browser window and uses them too.
Purchase event
Sent once per order, as soon as the order is confirmed, while the visitor sees the thank-you message. Available when the checkout happens in the embedded shop.
The fields follow the Google Analytics 4 purchase event, so you can pass the data on unchanged:
EventSquare("on", "purchase", function (purchase) {
// Google Analytics 4 (gtag.js)
gtag("event", "purchase", purchase);
// Google Tag Manager
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null, eventsquare: null });
window.dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: purchase.transaction_id,
value: purchase.value,
currency: purchase.currency,
items: purchase.items
},
eventsquare: {
event_id: purchase.event_id,
order_id: purchase.order_id,
test: purchase.test === true,
event: purchase.event,
edition: purchase.edition,
channel: purchase.channel
}
});
// Meta Pixel
fbq(
"track",
"Purchase",
{ value: purchase.value, currency: purchase.currency },
{ eventID: purchase.event_id },
);
});
Field | Example | Description |
|
| Order reference, as the visitor sees it and in the confirmation email. |
|
| Unique order ID. Use it so you don't count an order twice. |
|
| Event ID for Meta. Use it as the |
|
| Total amount paid, including fees. |
|
| Currency code according to ISO 4217. |
|
|
|
| see below | The tickets and products in the order. |
|
| The event. |
|
| The edition of the event. |
|
| The sales channel (shop). |
Each item in items:
Field | Example | Description |
|
| ID of the ticket type or product. |
|
| Name of the ticket type or product. |
|
|
|
|
| Price per item, excluding fees. |
|
| Number of items. |
|
| Discount per item. |
|
| Service fee per item. |
|
| For shows (dates / time slots): |
Tickets event
Sent when the confirmation of a completed order is shown, right after the purchase event, with the link to the visitor's tickets. Use it to show your own confirmation with tickets: 'none' (see After the order).
EventSquare("on", "tickets", function (order) {
console.log(order.url); // https://tickets.eventsquare.io/…
});
Field | Example | Description |
|
| Link to the visitor's tickets (view and download). |
|
| Unique order ID (the same as in the |
|
| Order reference (the same as in the |
Treat the ticket link like a password. Anyone with the link can open the tickets. Show it to the visitor, but never send it to analytics tools, tag managers or other third parties. That's why it's a separate event: you can forward the purchase data to your analytics unchanged.
Testing your tracking
You don't need to place an order to test your setup. EventSquare('test', event) sends a sample event on your page, with the same fields as a real event and test: true:
EventSquare('test', 'purchase'); // one event
EventSquare('test');
// all tracking events: add_to_cart, remove_from_cart, begin_checkout, purchase, tickets
Run it in your browser's developer console on the page with the embedded shop, or from your own code. The event only goes to the listeners on your page (EventSquare('on', ...)): nothing is sent to EventSquare, no order is created and no shop needs to be loaded. The sample purchase has a transaction_id that starts with TEST and a value of 50 EUR.
Keep test data out of your reports by checking the flag:
EventSquare("on", "purchase", function (purchase) {
if (purchase.test) return console.log("EventSquare test purchase", purchase);
gtag("event", "purchase", purchase);
});
Or, while testing with Google Tag Manager's preview mode (Tag Assistant), just forward them and check that your tags fire. Then place one real order to test the whole flow: a free ticket, or a test order through your ticket shop's test link (Test store in the admin, no real payment).
JavaScript API (for developers)
Once the embed script has loaded, you can also use the API directly. Add listeners for an instance right after init, in the same script (the shop loads asynchronously, so you don't miss anything):
var store = EventSquare.init({
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: "#eventsquare-store",
});
store.on("navigate", function (event) {
/* ... */
});
store.off("navigate", handler);
store.destroy(); // removes the shop from the page
Command | Description |
| Embed a shop. |
| Listen to an event from all embedded shops. |
| Stop listening. |
| Remove all embedded shops. |
| Send a sample tracking event ( |
| Look for new |
Instance | Description |
| Listen only to events from this shop. |
| Stop listening. |
| Remove this shop from the page. |
| The |
Single-page apps (React, Vue, Angular, …)
Load the embed script once, for example in your index.html. Create the shop when your component mounts, and remove it when it unmounts:
// React example
useEffect(() => {
const store = window.EventSquare.init({
store: "https://yourevent.eventsquare.store/en/edition/channel",
target: containerRef.current,
});
return () => store && store.destroy();
}, []);
target accepts either an element or a CSS selector.
Content Security Policy
Does your website use a Content Security Policy (CSP)? Then allow EventSquare (the shop, and the checkout and ticket pages on eventsquare.io that open in it):
script-src https://*.eventsquare.store;
frame-src https://*.eventsquare.store https://*.eventsquare.io;
Troubleshooting
The shop doesn't appear.
Open your browser's developer console. The embed script shows clear messages that start with
[EventSquare], for example when thestoreURL ortargetis missing.Check that your website builder hasn't removed the
<script>tags. If it has, use the HTML-only embed.Check your Content Security Policy.
Cookie banners and tag managers sometimes block scripts from unknown domains. The shop needs the embed script to work, so allow it.
The shop is cut off or has a scrollbar.
Remove any fixed
heighton the container or on the<iframe>.Check that you're using the latest embed code from the admin (with
embed/v1.js).
The shop disappears behind my sticky header when changing steps.
Set
scrollOffset(ordata-scroll-offset) to the height of your header.
Text is hard to read on my background.
Use
background: 'opaque'(ordata-background="opaque").
My listeners don't receive purchase events (or other tracking events).
First test your listener code with
EventSquare('test', 'purchase')in the developer console (see Testing your tracking).Add the listeners before
EventSquare('init', …)(see Setting up listeners).begin_checkout,purchaseandticketsonly work when the checkout happens in the embedded shop: don't setcheckout: 'window'.Test on a web server (
http://orhttps://), like your real website, not with an HTML file you open from your computer (file://).
Still stuck? Contact EventSquare support and include the URL of the page where you embedded the shop.
