Skip to main content

GA4 Analytics

Maya sends its own events to Google Analytics 4, so what happens inside the Maya widget shows up in your reports next to the rest of your site traffic.

Every event carries the same set of context parameters, listed in section 3, plus a few of its own. Section 4 covers the events one at a time.

1. What It Is​

The Maya widget is a separate application from your website, so it does not appear in your analytics on its own. Instead Maya sends a small set of events straight to GA4 whenever a visitor does something: sends a message, presses a button, opens a recommendation, follows a link in an answer.

Five interaction events are available to every client on both routes, so a report you build once keeps working. maya_identify is the sixth event, and it exists only on the direct Google-tag route; clients using the Tag Manager/data-layer route never receive it. More may be added as Maya grows, the search experiences in particular, and anything added follows the same shape: the parameters in section 3 on every event, plus a few of its own.

Events can go to two properties at the same time:

  • Your own GA4 property, so what visitors do in the widget sits beside your existing site reports
  • Maya's property, which we use to see how the product performs across all clients

You decide whether yours is one of them.

There are two ways the events reach you, and which one Maya uses depends on whether you give us a measurement ID. If your measurement is already managed in Google Tag Manager, the data layer route is the one to take, and we maintain a container you can import that sets it up for you — ask us for it.

With a measurement ID, through the Google tag. Maya loads Google's own tag, gtag.js, with the ID we set, and sends each event through it. The Google tag is a single piece of Google-supplied code you add to a page to send event data straight to Google Analytics, so once the ID is set there is nothing further to configure: the event arrives in the property that ID names, already shaped as a GA4 event. This is the route most clients are on, and it is the simpler one when the property is not already tagged through Tag Manager.

Without one, through the data layer. Maya pushes each event onto the page's data layer instead, and your Google Tag Manager container picks it up from there. The data layer is the object that both Tag Manager and the Google tag use to pass information to tags, and Tag Manager itself is a tag management system that lets you add and update tags from its own web interface instead of editing the code on your site. This is the route to take when your measurement is already managed in Tag Manager: you add a custom event trigger on the Maya event name and decide there where the data goes, or you import the container we maintain, which is that work already done.

The two routes are exclusive, and the measurement ID is the switch. Maya pushes to the data layer only when no measurement ID is set on your organisation at all. Give us an ID and every event goes through the Google tag instead and nothing reaches the data layer, so a Tag Manager container waiting on those events would sit silent. Ask us to clear the ID when you move to the data layer route.

The event carries the same information either way. Only the shape of the call differs: the event name, the parameters that belong to that event from section 4, and the eight context parameters from section 3.

Through the Google tag it goes out as a gtag event call:

gtag('event', 'maya_click_button', {
send_to: 'G-XXXXXXXXXX',
// the event's own parameters
button_type: 'quick_reply',
button_text: 'Show me family trips',
// the context parameters, on every event
chat_id: 'a1b2c3d4',
url: 'https://www.example.com/holidays',
organization: 'example',
domain: 'example.com',
mode: 'popover',
language: 'en',
test_user: false,
environment: 'production',
})

send_to names the measurement ID the event is for, and the call is repeated once per ID we were given, so each property receives the event directly and only the properties you asked for receive it.

On the data layer it goes out as a single push, with the event name under event, which is the key Tag Manager triggers on:

window.dataLayer.push({
event: 'maya_click_button',
button_type: 'quick_reply',
button_text: 'Show me family trips',
chat_id: 'a1b2c3d4',
url: 'https://www.example.com/holidays',
organization: 'example',
domain: 'example.com',
mode: 'popover',
language: 'en',
test_user: false,
environment: 'production',
})

2. Turning It On​

Send us the measurement ID of the property you want the events in. It looks like G-XXXXXXXXXX, and you will find it in GA4 under Admin, then Data streams, then your web stream.

We set it on your organisation and the widget picks it up the next time it loads, and there is nothing to add to your website: Maya loads Google's tag itself using the ID we set.

If that property is already tagged on the page, use the data layer route instead. Maya loading Google's tag for an ID your own site also loads means the page carries that tag twice, and each copy reports its own page_view — so your pageviews roughly double on every page the widget appears on. It is a quiet fault, because the inflation is there from the first day rather than appearing as a step change you would notice in a report. The data layer route avoids it entirely: Maya pushes the events and your existing tag, configured once in Tag Manager, is the only one on the page.

So: give us a measurement ID when the property is not already tagged on the site. Where it is, ask us to leave the ID empty and to send you the Tag Manager container instead.

Importing the Tag Manager container​

Before you import anything, ask us to check your Maya organisation. It must have no GA4 measurement ID configured at all — neither Maya's nor yours. If either ID is present, Maya loads Google's tag for that ID and sends through it instead; the data layer events never reach Tag Manager. This remains true even if your website already has GTM. If GTM also loads a Google tag for the same ID, both can send a page_view.

These are two different settings: the GA4 ID fields on your Maya organisation select the widget's direct-tag route and cause the widget to load a Google tag. The Maya - GA4 measurement ID override inside your GTM container, described below, only selects where GTM sends Maya event tags; it does not cause the widget to load another tag. For this GTM route, keep both Maya organisation ID fields empty even if you set the GTM override.

  1. Download the Maya GTM container.
  2. In Tag Manager, go to Admin → Import Container, select the file and choose the workspace that serves the site.
  3. Choose Merge, never the top-level Overwrite option, which would replace the whole container. On the first import choose Rename conflicting tags, triggers and variables. When you import a newer version later, choose Overwrite conflicting tags, triggers and variables so the existing Maya - objects are updated instead of duplicated.
  4. Review the import. It should add 5 tags, 5 triggers and 22 variables, all beginning Maya - .
  5. Use Preview to test the setup, then Submit / Publish when the checks below pass.

Import this file into every Tag Manager container that serves sites reporting to the property. Do not assume there is only one container per client or property. The same container is already in production with a live client.

It forwards five events: maya_sent_message, maya_click_button, maya_click_grid_item, maya_url_click_chat and maya_url_click_search. The shared context and each event's own parameters are already configured. url is deliberately not added as a custom event parameter, because GA4 records the page address as page_location already. After publishing, use the custom-dimension guidance immediately below to register the parameters you want available in reports.

Two optional constants control the setup. Maya - GA4 measurement ID override defaults to AUTO. The automatic resolver uses the page's existing Google tag only when it finds exactly one active, well-formed G- measurement ID; zero or several IDs make it fail closed and send nothing. Set the override when you need to choose the property explicitly. Maya - domain match defaults to ALL. It also accepts a hostname prefix with its trailing dot, comma-separated prefixes with spaces around the commas if you prefer, a bare regular expression, or a slash-wrapped regular expression. Invalid expressions fail closed. Prefer a prefix or a regular expression anchored at the start with ^, so one brand's container cannot pick up another brand's traffic.

The import expects an existing Google tag for the property. It does not install one. GA4 installed on its own does not automatically consume Maya's data layer events: the GTM triggers and event tags in this import do that forwarding. Without GTM, this template does not work; without an existing Google tag in the container, its event tags cannot send, so add a Google tag and set the measurement ID override. It also uses Custom JavaScript variables. If your container policy disallows them, do not make a second version of the JSON: manually replace the resolver with a Constant measurement ID and replace the domain-variable checks on the triggers with literal conditions.

To test it:

  1. Start Tag Manager Preview without adding ?is_test=true, because test-user traffic is excluded by the triggers.
  2. Send a message, press a quick reply or button, open a grid card, follow a link in a chat answer and follow a link in a search answer.
  3. For each action, confirm that the matching Maya - GA4 - … tag fires, its parameters are populated, the measurement ID is the intended one and Maya - domain allowed is true.
  4. Confirm the events in GA4 DebugView.
  5. If you scoped the setup by domain, open a site outside that scope and confirm the Maya tags do not fire there.

Two things worth settling before you build reports on this.

Register the parameters you want to report on. GA4 receives every parameter below, but reports and explorations only offer the ones you have registered. In GA4 go to Admin, then Custom definitions, then Create custom dimension, and enter the parameter name exactly as it is spelled here. Do this before you need the data, because GA4 does not fill in the past.

Values are cut at 100 characters. That is a GA4 limit rather than ours. It mostly shows on item_title and button_text, where a long trip name or a long piece of link text arrives truncated.

3. What Arrives With Every Event​

These are sent every time, regardless of which event it is. Whatever the visitor did, the event recording it also carries all eight parameters below, so you can group or filter any event by any of them without having to check first whether that particular event includes it:

ParameterWhat it is
chat_idThe identifier of the conversation. Every event from the same conversation carries the same value
urlThe full address of the page the widget was open on
organizationYour organisation's short name in Maya
domainThe hostname of the page, with www. removed, so one value covers your site whether or not the visitor used the www form
modeHow the widget was embedded: popover for the bubble in the corner, full-page for a page of its own, search or quick-search for the search experiences
languageThe language the conversation is being held in
test_usertrue when the conversation is one of ours or yours rather than a visitor's. See section 7
environmentWhich Maya environment sent the event. production is your live traffic

chat_id is the one to build on. It is the only parameter that ties several events together into one conversation, so counting distinct values of chat_id is how you count conversations, and it is what lets you see the order things happened in for a single visitor.

4. The Events​

maya_sent_message​

Sent when a message goes to Maya on the visitor's behalf. It counts the visitor's side of the conversation, not Maya's replies.

ParameterWhat it is
message_typeuser for something typed in the box, quick_reply for a suggested reply the visitor pressed, cta for a message a button sent on their behalf
message_subtypeOnly present when message_type is cta. Today the one value is leave_details, the message that starts the request for someone to get back to them

Asking Maya to try an answer again counts here too, as user, because that is what it sends.

maya_click_button​

Sent for every button in the widget. This is the busiest of the six, so button_type is what makes it readable.

button_typeWhere it isbutton_subtype
popover_iconThe bubble in the corner, and the controls in the widget's own frameopen_popover, close_popover, send_chat
notificationThe message that appears beside the bubble inviting someone to startopen_popover
tabSwitching between the conversation and the recommendations, in full page modeto_chat, to_recommendations
ctaA call to action inside the conversationleave_details when it asks for the visitor's details, continue_chatting when it returns to the conversation, and none at all for the button that opens the recommendations
quick_replyA suggested reply that you wrotenone
quick_reply_aiA suggested reply that Maya generatednone
restartStarting the conversation overnone

button_text carries the label the visitor actually saw, in their own language. It comes with calls to action, quick replies and tabs. The bubble, the notification and restart have no label to record, so they do not send it, and the conversation tab is always recorded as Chat rather than translated.

The two kinds of quick reply are worth keeping apart: quick_reply is one of yours and quick_reply_ai is one Maya wrote for that moment, so comparing them tells you whether your own suggestions are the ones people press.

maya_click_grid_item​

Sent when a visitor opens one of the recommendations Maya showed on the cards under the conversation.

ParameterWhat it is
item_urlThe address the visitor was sent to. This is the one to match against your own page reports
item_titleThe name of the trip or property, as shown on the card
item_subtitleThe price as it appeared on the card. It is a piece of text rather than a number, and it carries whatever currency and formatting the card showed
item_destinationThe first destination on the item. An item covering several destinations still reports one
item_typeThe label printed over the card's image. It comes from your own content, so what appears here is whatever you put there
item_entityWhat kind of thing was opened. Today this is always trips

Match on item_url****, not item_title****. Titles are cut at 100 characters and can be reworded in your content, while the URL is what your own reports are keyed on, so joining the two sides on the URL is what holds up over time.

maya_url_click_chat​

Sent when a visitor follows a link inside one of Maya's written answers, rather than on a recommendation card.

ParameterWhat it is
item_urlThe address the link pointed to
item_titleThe text of the link, as the visitor saw it
item_typeAlways text, which is what separates these from the card clicks above

This one comes from the chat widget only, in popover and full-page mode. The search experiences send maya_url_click_search instead, described next. Taken together with maya_click_grid_item, it is how you see the traffic Maya sends into your own site, recommendations in one event and links inside answers in the other.

The search counterpart of maya_url_click_chat. Sent when a visitor follows a link inside one of Maya's written answers in the search experiences, in search and quick-search mode, rather than on a recommendation card.

ParameterWhat it is
item_urlThe address the link pointed to
item_titleThe text of the link, as the visitor saw it
item_typeAlways text, which is what separates these from the card clicks above

The parameters are the same as on maya_url_click_chat, so a report built on one works on the other by changing the event name. The two are kept apart so that chat and search link clicks can be counted separately without filtering on mode.

The search experiences previously sent maya_url_click_chat for these clicks, so a report that reaches back before this event existed needs both names to cover search.

maya_identify​

Sent once per conversation, just before the first of the events above. It exists so a conversation can be tied to a visitor, which the next section explains.

This one is only sent on the Google tag route. It is raised as part of setting that tag up, so a client on the data layer route never receives it and never sees ga_client_id. The other five events are unaffected.

ParameterWhat it is
ga_client_idThe visitor's GA4 client identifier, when there is one to read. Absent otherwise, and the event is still sent

5. Tying a Conversation to a Visitor​

Maya reads the visitor's GA4 client identifier from the _ga cookie your own GA4 tag sets, sends it on maya_identify, and stores it on the conversation.

That cookie only exists if the visitor accepted analytics, so this follows your consent banner without needing to know anything about it. No consent means no cookie, which means no identifier, and the conversation is simply recorded without one. Nothing else about the visitor is read or stored.

Two things it buys you:

  • In your own GA4, ga_client_id lets you map a conversation onto the visitor GA4 already knows, if you want a user-scoped custom dimension for it
  • On our side, it is what allows purchases to be traced back to a conversation, which is the next section

It is sent once per conversation, on the first thing the visitor does, and not at all for a conversation that is only being read back rather than held.

6. Bringing Purchases Back to Conversations​

Whether someone chatted and then booked is a different question from the ones above, and the events cannot answer it on their own: the purchase happens on your site, well after the conversation, and usually on a page the widget never appeared on.

So it is answered from your GA4 export instead. If you send your GA4 data to BigQuery and give us access, we read your purchases and key events from it and attribute them to a conversation through the identifier from section 5. What we need is the BigQuery project and dataset of the export, your numeric property ID, and which events you count as a conversion.

The result is conversion figures per conversation, which is what the revenue reporting in your dashboard is built on. It is set up per client rather than on by default, so ask us if you want it.

7. Test Traffic​

Conversations we or you run as tests are marked, so you can keep them out of your reporting.

  • test_user is true on every event from a test conversation. Filtering it out is worth doing on any report you share
  • environment is production only for your live traffic, so our development and staging environments are easy to exclude in one go
  • Events from those environments, and from a test conversation the widget already knows about when it loads, are also flagged to GA4 as debug traffic. That puts them in GA4's DebugView and keeps them out of the standard reports

That last point is also the quickest way to check a new setup: open DebugView in GA4, use the widget, and watch the events arrive as you click.

8. When You Do Not See Events​

Nothing arrives at all. On the Google tag route the likeliest reason is that no measurement ID is set on your organisation, because Maya sends nothing rather than guessing where to put it. Ask us to check. On the data layer route it is the opposite: a measurement ID that is still set stops the push, so ask us to clear it. If there is no Google tag, or the automatic resolver finds zero or several measurement IDs, the Tag Manager tags fail closed: check the resolver, add a Google tag and/or set the override. Beyond that, an ad or tracking blocker in the browser stops these events exactly as it stops your own.

The events arrive, but the parameters are missing from reports. They are being received and are not yet registered. See the custom dimensions step in section 2. A dimension you register now only fills from now on.

maya_identify has no ga_client_id****. The visitor did not accept analytics, or your own GA4 tag is not on the page the widget was opened from. Both are expected rather than a fault.

A value looks cut off. It reached 100 characters, which is GA4's limit. Match on item_url rather than on titles.

The numbers do not match your dashboard. Your dashboard counts every conversation. GA4 only ever sees the ones where the visitor did something, because every event here is triggered by an action, so a conversation that was opened and abandoned appears in one and not in the other.

Events go to one property but not the other. Each property is configured separately, so a missing or mistyped measurement ID stops that one alone and leaves the other looking healthy. Check which property you are reading before assuming the events are gone.