Google Analytics 4 on hosted litecheckout
Hosted litecheckout can load your Google Analytics 4 tag on the checkout page and send three events to your own property. You enter a measurement ID once in Merchant Admin; litecommerce owns the loader, the event payloads, the consent defaults, and the Content-Security-Policy. There is no script field, no Tag Manager container, and nothing to paste — a hosted checkout is a payment surface, so only this reviewed, platform-owned integration runs on it.
Scope of the first release. Ordinary cart checkout at /session/<token>
only. Booking and subscription checkouts, the order-status page, and the
signed-in account center send nothing. The capability reaches your Preview
surface with the release that carries it and production with the promotion
of that same release. You can tell whether your environment has it: the
Google Analytics 4 section appears under Settings → Checkout, and the
anonymous organization snapshot (GET /api/v1/organizations/{slug}) carries
a ga4MeasurementId key (null until you activate). If neither is present,
your environment does not have the capability yet.
Configure it
- In Google Analytics, create or choose the GA4 property and web data stream for your store. Use a separate property for Preview (see environments below) so test orders never land in production reporting.
- In Merchant Admin go to Settings → Checkout → Google Analytics 4 and
enter the stream's measurement ID (
G-XXXXXXXXXX). Universal Analytics (UA-), Tag Manager (GTM-), and Ads (AW-) identifiers are rejected. Anyone with settings permission can enter, change, or clear the ID. - Have a tenant Owner or Admin tick "My published privacy policy
discloses Google Analytics use on hosted checkout." Only an Owner or
Admin can record this attestation; Merchant Admin disables the box for
everyone else. Until it is recorded the ID is saved but no tag
renders — the public snapshot reports
ga4MeasurementId: null— so Staff can enter the ID first and an Owner or Admin can attest later. - Save. To turn the tag off, clear the field and save: that also clears the attestation, and the next checkout page load carries no tag. Changing the ID to a different value clears the attestation too; the new ID stays dark until an Owner or Admin records the disclosure again.
Each attestation, and each clear or change of an attested ID, is recorded in your organization's audit log with the acting user, the timestamp, and the measurement ID (the attested statement is stored verbatim on the attestation entry).
The measurement ID is public by nature (it ships in every tagged page), so
once activated it is also readable on the anonymous organization snapshot
(GET /api/v1/organizations/{slug} → ga4MeasurementId). That projection
exists to serve the hosted checkout tag. If you read it to tag your own
storefront or a BYO checkout, that is your own integration with its own
disclosure obligations: none of the hosted checkout's safeguards described
below (the sanitized locations, the consent defaults, the Content-Security-
Policy, the verified purchase) travel with the value. The attestation
timestamp stays merchant-only.
Environments
| You are on | The value you save reaches | Recommended property |
|---|---|---|
admin.preview.litecommerce.io | {tenant}.preview.litecheckout.io only | a Preview-only GA4 property |
admin.litecommerce.io | {tenant}.litecheckout.io only | your production property |
Each environment stores its own value, and litecheckout additionally refuses to render the tag unless the request host is exactly your tenant's canonical host for that environment — never a per-PR deployment URL or a local development host. Prefer a separate property over GA4 data filters for test traffic: a filter is permanent once applied and the filtered stream still receives the events.
What litecheckout sends
The tag loads gtag.js from www.googletagmanager.com as an ordinary
asynchronous script after the page has rendered — it never blocks checkout,
and a blocked or failed load leaves checkout untouched. Google serves gtag.js
unversioned, so it cannot carry Subresource Integrity; the platform admits it
by host allowance on the checkout-session route only. The tag runs with:
send_page_view: false— the automatic page view is replaced by the sanitized manual one below;page_locationfixed at config level tohttps://{your checkout host}/session; litecheckout's own in-page URL changes (after a payment-provider return and when an expired checkout is recovered in place) go through ahistory.replaceStatereference captured before the tag loads, so the tag's history hook never sees them and a history-based page view cannot carry the checkout link — that bypass is the guard, and the sanitized location is re-applied afterwards only so later events keep it;page_referrerfixed at config level to the referrer's origin only;cookie_domainpinned to your exact checkout host, so_gais never shared across tenants onlitecheckout.io;allow_google_signals: falseandallow_ad_personalization_signals: false;- no
user_id, no user properties, and no debug mode.
| Event | When | Parameters and where they come from |
|---|---|---|
page_view | one manual page view per checkout page load, sent by litecheckout (litecheckout's own in-page URL changes, after a payment-provider return and when an expired checkout is recovered in place, are invisible to your stream's history-events option, so that option adds no page views here) | page_location = https://{tenant}.litecheckout.io/session in production and https://{tenant}.preview.litecheckout.io/session on Preview (the checkout token and every query parameter are removed); page_referrer = the referrer's origin; page_title = "Secure checkout". |
begin_checkout | once per checkout session per browser tab, when the session first renders as payable | currency (ISO 4217, upper case); value; items. |
purchase | once per order per browser, only after the server reports the session CONFIRMED with an order number | transaction_id = your order number; currency; value; tax; shipping; items. |
Per Google's guidance, value is the sum of price × quantity over the
items after discounts and excludes shipping and tax; both ride separately on
purchase. A cart-level discount is allocated across the lines in proportion
to their totals, so each entry in items carries item_id (the catalog
variant id, or the item id when the line has no variant), item_name (the
line name as it appears on the order), price (the discounted unit
price), discount (the per-unit reduction, when a discount applies), and
quantity. Unit prices may carry more decimals than the currency's minor
unit so that item revenue and value reconcile exactly. Amounts are reported
in major units at the currency's own precision (a zero-decimal currency such
as JPY reports whole yen). Package component rows are excluded so item totals
reconcile to the subtotal.
Why the purchase is verified and not duplicated
The purchase never fires from the Stripe return URL's redirect_status — that
lands before the payment webhook and could be forged. It fires only when the
authoritative session read says CONFIRMED and carries the order number, and
the browser remembers each order number it has already reported so a reload,
a back navigation, or a return to the confirmation page does not send it
again. GA4 additionally deduplicates web-stream purchases that share a
transaction_id.
What is never sent
The checkout link token, the Stripe PaymentIntent client secret, card data,
the shopper's email, phone, name, addresses, customer id, and account state.
Unit tests pin these exclusions on every payload and on page_location.
Enhanced measurement on your stream
GA4's enhanced measurement settings belong to your data stream and stay
under your control. litecheckout neutralizes the automatically collected
parameters that could otherwise carry the checkout URL: every form on the
checkout page has a sanitized action (form_destination = /session), the
referrer is origin-only, the outbound-click link_url can only ever be a
link you configured (your store, your policies, your support contact — never
a checkout or order-status link), and litecheckout's own in-page URL changes
bypass the tag's history hooks, so the history-events option never sees them.
If a shopper's content blocker stops the primary collection endpoint, the tag
retries on www.google.com, which the checkout policy deliberately excludes;
the browser then sends a Content-Security-Policy violation report to
litecommerce's own collector, and no analytics hit reaches Google. If you do not want form-interaction, outbound-click,
site-search, or history-based page-view events from checkout at all, turn
those options off on the stream; the platform does not change your stream
settings.
Consent defaults
Before the tag loads, litecheckout declares consent-mode defaults on every
checkout page: ad_storage, ad_user_data, and ad_personalization are
denied everywhere; analytics_storage is granted on the notice-based
posture, except for visitors in the EU member states, the EEA (Iceland,
Liechtenstein, Norway), the United Kingdom, Switzerland, and the related
territories (Åland, French Guiana, Guadeloupe, Martinique, Saint Martin,
Réunion, Mayotte, Gibraltar, Jersey, Guernsey, Isle of Man), where it is
denied and those visitors are measured without cookies.
These defaults are the same for every tenant and every shopper. A consent
choice a shopper made on your storefront does not carry into hosted
checkout in this release: a shopper who declined analytics on your
storefront is still measured on checkout under the defaults above. If your
storefront asks for opt-in consent, hold your attestation: the platform is
building a handoff that carries the storefront choice into checkout, and
asks opt-in storefronts to activate once it ships. Your privacy policy must
describe what checkout does. litecheckout has no consent banner; the
platform's /cookies notice on your checkout host lists the _ga cookies
when your tag is active, and says so explicitly when it could not confirm
your configuration for a request. Your privacy policy must disclose your use
of Google Analytics before you activate the tag — that is what the
attestation records.
Keep attribution across your storefront and checkout
Your storefront and {tenant}.litecheckout.io are different domains. This
section applies to shoppers whose analytics storage is granted: Google's
linker carries the _ga client id, so visitors measured without cookies in
the regions listed under consent defaults start a new client on each domain
whatever you configure, and their checkout is reported separately. For every
other shopper, for GA4 to treat the storefront visit and the checkout as one
session:
- Install the same measurement ID on your storefront (the Preview ID on
your preview storefront, the production ID on your production storefront),
in the top-level document. Google's cross-domain linker works only when
the storefront tag can keep the
_gacookie and decorate the links on the page. A tag loaded in a sandboxed or opaque-origin frame can do neither, so the checkout visit starts a new client no matter what else you configure. - In GA4 admin, under the web data stream's tag settings, configure your
domains to include both your storefront host and your same-environment
checkout host (
{tenant}.litecheckout.iofor production,{tenant}.preview.litecheckout.iofor Preview). Google's tag then decorates navigation between them with the_gllinker parameter. This helps only when your storefront tag can decorate; otherwise it merely adds_glto hosted checkout's "Return to store" links. - Under list unwanted referrals, add
stripe.com, so a shopper returning from a 3-D Secure or bank redirect is not counted as a new referral session. - Make the handoff to checkout a link the shopper clicks. Google documents
that the linker decorates link clicks and form submissions, not navigation
triggered purely by JavaScript. If your storefront creates the checkout
session and then navigates with
window.location, the checkout page arrives without_gland GA4 starts a new session attributed to a referral from your storefront. Render the session URL as an anchor once the session exists, or trigger the navigation through a real anchor click, and verify in your browser that the litecheckout URL carries_gl. - Keep Google signals off on the property. The hosted tag disables them, and the checkout CSP deliberately admits no advertising endpoints, so a property with signals on produces blocked, reported requests rather than data.
The "Return to store" link on the confirmation page is an ordinary anchor, so the return trip is decorated automatically once your domains are configured.
Verify
GA4's DebugView shows only sessions running in debug mode, and the hosted
tag never sets debug_mode, so enable a debug session in your own browser
first (Google's Analytics Debugger extension, or the steps DebugView itself
lists) — otherwise DebugView stays empty even though events are arriving.
The Realtime report needs no setup and shows the same events with a short
delay. Verify from a location where analytics storage is granted (or with a
non-EU/EEA/UK/Swiss geolocation), otherwise the cross-domain checks below
cannot pass by design. Then start a checkout on {tenant}.preview.litecheckout.io with the
Preview property configured and complete a test payment. You should see one
page_view whose location ends in /session with no token, one
begin_checkout with the expected value and items, and exactly one
purchase with transaction_id equal to the order number — and no second
purchase after reloading the confirmation page. In the browser's network
panel, every request to Google hosts should be free of the checkout token,
the client secret, and any customer detail. Requests the checkout page's
Content-Security-Policy blocks (for example advertising endpoints from a
property with signals on) show as CSP violations in the browser console.
Who owns what
litecommerce owns the tag, the events and their payloads, the consent defaults, and the checkout page's Content-Security-Policy, and can remove the Google hosts from that policy in an emergency. You own the GA4 property, its data-stream settings (including enhanced measurement), your storefront tag, and your privacy disclosure. Clearing the measurement ID in Merchant Admin stops the tag on every checkout page loaded from then on; a checkout that is already open keeps the tag it loaded until that page reloads.
Limits: browser analytics versus your order ledger
GA4 counts what a browser managed to send. It undercounts and cannot be reconciled to Admin:
- ad blockers and privacy browsers block the tag host outright;
- a shopper who closes the tab before the confirmation renders sends no purchase;
- visitors in the cookieless regions are measured without cookies, and denied or unsupported browsers may send nothing;
- Safari caps script-set cookies at seven days, so returning-visitor attribution decays;
- orders placed through POS, Merchant Admin, invoices, bookings, or subscriptions never pass through the tag;
- refunds, cancellations, and chargebacks are not reflected.
The Orders ledger in Merchant Admin and its exports remain the only source of truth for revenue and order counts.
Not included
add_shipping_info and add_payment_info, SKU and coupon codes on the items,
server-side Measurement Protocol delivery (including refund), tags on the
order-status or account surfaces, Google Tag Manager, advertising pixels, a
consent banner, and carrying a storefront consent choice into checkout. These
are tracked follow-ups, not launch dependencies.
Related
- Hosted litecheckout — the surface this tag runs on
- Storefront integration — the storefront side of the handoff
- BYO checkout API — rendering your own checkout, which this tag does not cover