Skip to main content

Embed your ticket shop on your website

Put your ticket shop and checkout on a page of your own website, with the code from your integrations.

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:

  1. The <div> marks the spot on your page where the shop appears.

  2. The first <script> sets up the shop. It can run before the EventSquare script has loaded: the calls are queued and run afterwards.

  3. The last <script> loads the EventSquare embed script. Because of async, 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

store

data-eventsquare-store

—

Required. The URL of your ticket shop.

target

—

—

Required (JavaScript embed). CSS selector or element the shop goes into, e.g. '#eventsquare-store'.

background

data-background

'transparent'

'transparent': the shop blends into your page. 'opaque': the shop gets its own background color, useful on dark or busy backgrounds.

scrollOffset

data-scroll-offset

16

Space in pixels above the shop when it scrolls into view (see Scrolling). Set this to the height of your fixed (sticky) header.

minHeight

—

450

Height in pixels kept free while the shop loads, and the smallest height the shop gets.

title

data-title

'Ticket shop'

Title of the embedded frame, read out by screen readers.

checkout

data-checkout

'inline'

'inline': the checkout happens in the embedded shop (see Checkout and payment). 'window': visitors continue to the EventSquare checkout page in the full browser window.

tickets

data-tickets

'button'

After the order:
​'button' shows a thank-you message with a button that opens the tickets in a new window.
​'redirect' shows the tickets automatically in the embedded shop.
​'none' shows nothing: the embedded shop disappears and you show your own confirmation. See After the order.

tracking

data-tracking

'host'

'host': your tracking tags (Google Analytics, Google Tag Manager, Meta, TikTok) run on your page, using the tracking events; the integrations you connected in the EventSquare admin don't run in the embedded shop.
​'frame': they also run in the embedded shop, like on your regular shop page. See Tracking and cookie consent.

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 width or max-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:

  1. Visitors choose their tickets and fill in their details in the embedded shop.

  2. 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.

  3. Free orders and invitations don't need a payment, so there is no popup.

  4. 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):

tickets

What visitors see

'button' (default)

A thank-you message with a button that opens the tickets in a new window.

'redirect'

The tickets right away, in the embedded shop.

'none'

Nothing from EventSquare: the embedded shop disappears and you show your own confirmation with the tickets event.

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

ready

—

The shop has loaded.

resize

{ height }

The height of the shop changed (in px).

navigate

{ path }

The visitor went to another step or page in the shop.

add_to_cart

see Tracking events

Tickets were added to the cart.

remove_from_cart

see Tracking events

Tickets were removed from the cart.

begin_checkout

see Tracking events

The visitor started the checkout (once per cart).

purchase

see Purchase event

An order was completed (paid, free or invitation).

tickets

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 with data-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: a ready listener added later is still called.

  • The examples below leave out the loader and init to 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

add_to_cart

add_to_cart

AddToCart

AddToCart

Shop

remove_from_cart

remove_from_cart

—

—

Shop

begin_checkout

begin_checkout

InitiateCheckout

InitiateCheckout

Checkout (inline)

purchase

purchase

Purchase

Purchase

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

transaction_id

"HRG66616"

Order reference, as the visitor sees it and in the confirmation email.

order_id

"05ab4e26-e168-…"

Unique order ID. Use it so you don't count an order twice.

event_id

"123456789012"

Event ID for Meta. Use it as the eventID of a Meta Purchase: Meta then combines the purchase from your website with the one from the Conversions API.

value

22.28

Total amount paid, including fees. 0 for free orders.

currency

"EUR"

Currency code according to ISO 4217.

invitation

false

true if the order is an invitation.

items

see below

The tickets and products in the order.

event

{ "id": "682075652458", "name": "Demo" }

The event.

edition

{ "id": "059710758584", "name": "2027" }

The edition of the event.

channel

{ "id": "620258808826" }

The sales channel (shop).

Each item in items:

Field

Example

Description

item_id

"451871480410"

ID of the ticket type or product.

item_name

"Entrance ticket"

Name of the ticket type or product.

item_category

"ticket"

"ticket" or "product".

price

10

Price per item, excluding fees.

quantity

2

Number of items.

discount

0

Discount per item.

fee

1.14

Service fee per item.

show

null

For shows (dates / time slots): { id, name }.

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

url

"https://tickets.eventsquare.io/10c1b57b-…"

Link to the visitor's tickets (view and download).

order_id

"05ab4e26-e168-…"

Unique order ID (the same as in the purchase event).

transaction_id

"HRG66616"

Order reference (the same as in the purchase event).

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

EventSquare('init', options)

Embed a shop. EventSquare.init(options) returns the instance.

EventSquare('on', event, callback)

Listen to an event from all embedded shops.

EventSquare('off', event, callback)

Stop listening.

EventSquare('destroy')

Remove all embedded shops.

EventSquare('test', event)

Send a sample tracking event (test: true) on your page, see Testing your tracking. Without event: all tracking events.

EventSquare.scan()

Look for new data-eventsquare-store elements (after you've added them dynamically).

Instance

Description

instance.on(event, callback)

Listen only to events from this shop.

instance.off(event, callback)

Stop listening.

instance.destroy()

Remove this shop from the page.

instance.iframe

The <iframe> element.

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 the store URL or target is 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 height on 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 (or data-scroll-offset) to the height of your header.

Text is hard to read on my background.

  • Use background: 'opaque' (or data-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, purchase and tickets only work when the checkout happens in the embedded shop: don't set checkout: 'window'.

  • Test on a web server (http:// or https://), 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.

Did this answer your question?