Google Tag Manager on your market site
Updated 9 October 2026
Your market's public site can load your own Google Tag Manager container. StallsApp pushes a small, fixed set of events into it — every page viewed, a ticket checkout started, a ticket order completed with its value, a stall application sent — and what your container does with them is up to you: Google Analytics 4, a Google Ads conversion, a TikTok or Pinterest tag, anything Tag Manager can hold. This guide shows exactly what is pushed, under what names, and how to pick each value up in Tag Manager.
If all you want is Meta (Facebook) conversions, you don't need Tag Manager: paste your Pixel ID on the same page and the same events go straight to Meta.
Add your container
In Tag Manager, the container ID is at the top of your workspace, next to the container name — it looks like GTM-XXXXXXX. In StallsApp, open the market, go to Marketing under Public website, paste the ID into the Google Tag Manager field and save. That's the whole install: there is no snippet to paste, because the container is loaded for you.
The container loads on your published public pages only — the home page, market days, stallholders, the application form, the tickets page, the thank-you page after checkout, and any content pages you've published. It is never loaded on draft previews, on a buyer's ticket receipt, or on anyone's account pages, and it is never given a page address that carries a login token. Clearing the field removes the container from your site.
The data layer, and why ours has its own name
Tag Manager reads a list in the page called the data layer. A website pushes small objects onto it — "a purchase just happened, here is the value" — and tags in your container fire on them and read their fields. Most sites use the default name, dataLayer. StallsApp uses its own, marketDataLayer, and passes that name to your container when it loads it.
The reason is isolation. StallsApp runs its own analytics on every page to understand how the platform is used, and that traffic uses the default data layer. A separate layer means your container sees exactly the events listed below and nothing of ours, and our analytics never sees anything your tags push. You don't have to do anything about the name: Tag Manager's preview mode, its Data Layer Variables and its Custom Event triggers all follow the layer the container was loaded with. The only time the name matters is if you write a Custom HTML tag that pushes its own events — push them to marketDataLayer, not dataLayer.
The events we push
Four events, each with the fields a tag typically needs attached directly to the push. The names follow the Google Analytics 4 recommended events where one exists, so a GA4 tag recognises begin_checkout and purchase as ecommerce without any renaming.
{
event: "page_view",
page_path: "/m/your-market/tickets",
page_location: "https://your-market.stallsapp.com/tickets",
page_title: "Entry tickets — Your Market · StallsApp"
}{
event: "begin_checkout",
currency: "AUD"
}{ ecommerce: null }
{
event: "purchase",
value: 24,
currency: "AUD",
transaction_id: "3f9c0b2a1d7e4c8f9b6a5d4e3c2b1a09",
ecommerce: {
transaction_id: "3f9c0b2a1d7e4c8f9b6a5d4e3c2b1a09",
value: 24,
currency: "AUD",
items: [{ item_name: "Entry tickets", quantity: 2, price: 12 }]
}
}{
event: "submit_application"
}Values are in whole currency units — 24 means $24.00 — and the currency is the one your organisation charges in. The transaction ID is a stable code derived from the order, so a buyer refreshing the thank-you page produces the same ID and GA4 or Google Ads can count the sale once. It is not the order number and can't be used to look an order up.
Reading a value: Data Layer Variables
To use any of those fields in a tag, give it a variable in Tag Manager. Go to Variables, choose New under User-Defined Variables, pick the Data Layer Variable type, and type the field's name exactly as it appears in the push. Leave the version at Version 2 (the default). Name the variable whatever helps you — "DL – value" is a common convention. One variable per field you plan to use:
| Data Layer Variable Name | Present on | What it holds |
|---|---|---|
| page_path | page_view | The page's path, e.g. /m/your-market/tickets |
| page_location | page_view | The full page address |
| page_title | page_view | The page's title |
| currency | begin_checkout, purchase | The three-letter currency code, e.g. AUD |
| value | purchase | The order total in currency units (24 = $24.00) |
| transaction_id | purchase | A stable code for the order, for counting each sale once |
| ecommerce.items | purchase | The GA4 items list: one entry, with item_name, quantity and price |
| ecommerce.items.0.quantity | purchase | How many tickets were in the order |
Dots walk into nested objects, so ecommerce.items.0.quantity reaches the ticket count inside the items list. A variable that isn't present on the current event is simply undefined — a page_view carries no value, and that's fine.
Firing a tag on an event: Custom Event triggers
Tags fire on triggers, and the trigger for any of our events is a Custom Event. Go to Triggers, choose New, pick Custom Event as the type, and enter the event name — purchase, begin_checkout, submit_application or page_view — exactly, in lower case. Leave it firing on All Custom Events unless you want to narrow it. Then on your tag, choose that trigger.
For page views you usually don't need our event at all: a Google tag or GA4 configuration on the standard All Pages trigger fires when the container loads, and GA4's enhanced measurement follows page changes on its own. Our page_view exists for tags that need a reliable per-page event with the path attached — a retargeting pixel, say — and for sites that have turned enhanced measurement off. Don't fire a GA4 page_view event on it as well as letting the Google tag send one, or every page counts twice.
Google Analytics 4
Add a Google tag with your GA4 measurement ID (G-…) on the Initialization – All Pages trigger. That gives you page views, sessions and traffic sources on their own.
For sales, add a Google Analytics: GA4 Event tag with the event name purchase, fired on your purchase Custom Event trigger. Under More Settings, open Ecommerce, tick Send Ecommerce data and leave the data source as Data Layer. GA4 then reads the ecommerce object — transaction_id, value, currency and the items — and the sale appears in Monetisation reports with revenue, without you mapping a single parameter by hand. Do the same with a begin_checkout event tag on the begin_checkout trigger if you want the checkout funnel.
Applications aren't an ecommerce event, so send them as a plain GA4 event: a GA4 Event tag named submit_application on the submit_application trigger. In GA4, open Admin, then Events, and mark it as a key event (what GA4 used to call a conversion) so it shows up as a goal in your acquisition reports.
Google Ads conversions
Create the conversion action in Google Ads (Goals, then Conversions, then New conversion action, Website, and add it manually) and note its Conversion ID and Conversion Label. In Tag Manager, add a Google Ads Conversion Tracking tag with those two values, fired on the purchase Custom Event trigger. Set Conversion Value to your {{DL – value}} variable, Transaction ID to {{DL – transaction_id}}, and Currency Code to {{DL – currency}} — the transaction ID is what stops a refreshed thank-you page being counted as a second sale.
Add a Conversion Linker tag on All Pages as well. It's what lets Google Ads tie a click on your ad to the purchase that happens a few pages later, and ads that link to your tickets page won't attribute without it. A second conversion action on the submit_application trigger, with no value, counts stall applications the same way.
What is deliberately not there
Nothing a visitor types reaches the data layer. No names, no email addresses, no order numbers, no ticket codes — not on the purchase, not on the application, not on any page. The transaction ID is derived from the order, not the order number itself. That is also a condition of using tags on StallsApp under our terms: your container must not be configured to read what visitors enter into the application or checkout forms, and you are responsible for every tag it loads and for your own privacy notice. Our privacy policy tells visitors that a market's pages may carry an organiser's container.
Expect your figures to sit a little below the sales and applications you see in StallsApp. Visitors with an ad blocker or browser tracking protection don't load the container at all, and that's a growing share of phones. StallsApp's own counts are the complete record; the container is for attribution — which ad, post or link brought the sale.
Checking it works
Use Tag Manager's Preview mode. Click Preview in your workspace, enter your market's public address, and Tag Assistant opens your site with a panel showing every event as it arrives — you'll see gtm.js, then page_view, then whatever you do next. Click through to the tickets page and submit the form to see begin_checkout; complete a free or test order to see purchase with its values. The panel's Variables tab shows what each of your Data Layer Variables resolved to on that event, which is the quickest way to catch a typo in a variable name.
Preview also works before you publish the container, so build the whole setup, confirm it in Preview, then Submit and Publish. Changes to your container take effect on your site immediately; nothing needs to change in StallsApp.
Run your market on StallsApp
Applications, approvals, stall payments, ticketing and market-day tools in one place. Free to start — no card required.
Get started free