Tip: you don't have to write the code yourself. In the EventSquare admin, open your shop and go to Embed on your website. You'll find a ready-to-copy code snippet there, already filled in for your shop.
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 can find it in the admin).
What this code does:
The
<div>marks the spot on your page where the shop appears.The first
<script>configures the shop. It can run before the EventSquare script has loaded: the calls are queued and replayed.The last
<script>loads the EventSquare embed script.asyncmeans 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 strip it. Use this version instead: no JavaScript configuration needed.
<div data-eventsquare-store="https://yourevent.eventsquare.store/en/edition/channel"></div>
<script src="https://yourevent.eventsquare.store/embed/v1.js" async></script>
Options are set 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 to place the shop in, e.g. |
|
|
|
|
|
|
| Space in pixels kept above the shop when it scrolls into view (see Scrolling). Set this to the height of your sticky header. |
| — |
| Height in pixels reserved while the shop loads, and the smallest height the shop gets. |
|
|
| Title of the embedded frame, read by screen readers. |
|
|
|
|
|
|
| After the order: |
Language
The language is part of the store 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 picks the visitor's browser language.
For a multilingual website, use the store 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, set a width or
max-widthon the container:<div id="eventsquare-store" style="max-width: 800px; margin: 0 auto;"></div>
The height is automatic. Don't set a fixed height on the container.
The shop has rounded corners and its own styling, and uses the brand colour you set in the EventSquare admin. You don't need extra CSS.
On dark or photo backgrounds, use
background: 'opaque'so all text stays readable.
Scrolling
When a visitor moves to the next step (for example from Tickets to 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 sticky header, set scrollOffset to its height so the shop doesn't end up 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 inside 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 inside embedded frames. Meanwhile the shop shows a message with a button to reopen the payment window, in case it was closed. When the popup is blocked (for example in some in-app browsers), the payment opens in the full browser window instead.
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, inside the embedded shop, right away. |
| Nothing from EventSquare: the embedded shop disappears, and you show your own confirmation using 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 to log analytics.
Event | Data | When |
| — | The shop has loaded. |
|
| The shop changed height (in px). |
|
| The visitor moved 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, so your listeners are in place before the shop starts and no event is missed:
<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: add 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 (it's safe to run more than once) 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
initfor brevity.
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, so you can measure them with your own tags on your website:
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, cart or order), items (see Purchase event), plus event, edition and channel. begin_checkout and purchase are only sent when the checkout takes place inside the embedded shop (checkout: 'inline', the default).
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: 'PlaceAnOrder' };
['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 });
window.dataLayer.push({ event: name, ecommerce: data });
// 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 event from EventSquare's own pixel (no double counting)
fbq('track', metaEvents[name], summary, name === 'purchase' ? { eventID: data.order_id } : undefined);
}
if (window.ttq && tiktokEvents[name]) ttq.track(tiktokEvents[name], summary);
});
});Connected your pixels in the EventSquare admin as well?
Those also fire inside the embedded shop. Browsers increasingly block tracking inside embedded frames, so measuring on your own page is more reliable. To avoid counting conversions twice, use one of both, or deduplicate (e.g. Meta's eventID).
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 takes place inside the embedded shop.
The fields follow the Google Analytics 4 purchase event, so you can pass the data on as it is:
EventSquare('on', 'purchase', function (purchase) {
// Google Analytics 4 (gtag.js)
gtag('event', 'purchase', purchase);
// Google Tag Manager
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'purchase', ecommerce: purchase });
// Meta Pixel
fbq('track', 'Purchase', { value: purchase.value, currency: purchase.currency }, { eventID: purchase.order_id });
});Field | Example | Description |
|
| Order reference, as shown to the visitor and in the confirmation email. |
|
| Unique order id. Use it to avoid counting an order twice. |
|
| Total amount paid, including fees. |
|
| ISO 4217 currency code. |
|
|
|
| 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 |
|
| Ticket type or product id. |
|
| 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 (same as in the |
|
| Order reference (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 is a separate event: the purchase data can be forwarded to analytics as it is.
Testing your tracking
You don't need to place an order to test your setup. EventSquare('test', event) fires a sample event on your page, with the same fields as a real one and test: true:
EventSquare('test', 'purchase'); // one event
EventSquare('test'); // all tracking events: add_to_cart, remove_from_cart, begin_checkout, purchase, ticketsRun 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 has to be loaded. The sample purchase has a transaction_id starting with TEST and a value of 50 EUR.
Leave 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), keep forwarding them and check that your tags fire. Then place one real order to test the whole flow: a free ticket, or a paid one through the shop's preview link in test mode (no real payment).
JavaScript API (for developers)
After the embed script has loaded, you can also use the API directly. Add instance listeners right after `init`, in the same script (the shop loads asynchronously, so nothing is missed):
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 pageCommand | Description |
| Embed a shop. |
| Listen to an event of all embedded shops. |
| Stop listening. |
| Remove all embedded shops. |
| Fire a sample tracking event ( |
| Look for new |
Instance | Description |
| Listen to events of this shop only. |
| 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. Then 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 an element as well as a CSS selector.
Content Security Policy
If your website uses a Content Security Policy (CSP), allow EventSquare (the shop, and the checkout and tickets pages on eventsquare.io that open inside 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 logs clear messages starting with
[EventSquare], for example when thestoreURL ortargetis missing.Check that your website builder didn't remove the
<script>tags. If it did, use the HTML-only embed.Check your Content Security Policy.
Cookie banners and tag managers sometimes block scripts from unknown domains. The embed script is necessary for the shop to work, so allow it.
The shop is cut off, or has a scrollbar.
Remove any fixed
heighton the container or on the<iframe>.Make sure you use 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").
Still stuck? Contact EventSquare support with the URL of the page where you embedded the shop.
