This post shows, in a direct and practical way, how to use AI Web Push events in Google Tag Manager (GTM), how to enable debug mode, and how to build metrics and conversions based on these events. No extra SDK is needed: everything reaches GTM via dataLayer.push.
Updated for version 1.9.3 of the plugin. Version 1.9.3 adds two new events, ai_web_push_permission_timeout and ai_web_push_subscription_skipped, and two new origins in push_source. What changed with Chrome 155 is covered in the post The Chrome notification prompt changed on Android.
Overview
Push events are sent to GTM via the dataLayer with the prefix ai_web_push_... and provider ai_web_push.
The push_source field indicates the origin:
- custom_modal: flow through a custom modal.
- native_prompt: flow directly through the browser's native prompt.
- site_controls means the visitor allowed notifications later, through the site controls in the browser. It appears in the subscription events, starting with version 1.9.3.
- permission_preexisting means the visitor had already granted permission in the browser but was not yet registered in AI Web Push, and the plugin registers them on the next visit. It appears in the subscription events, starting with version 1.9.3.
Starting with version 1.7.5, the plugin automatically detects whether the browser supports push notifications. If it doesn't (Instagram, Facebook, or TikTok WebViews, iOS Safari outside a PWA, contexts without HTTPS), the ai_web_push_browser_not_supported event fires and the flow ends without errors.
Optional debug mode: localStorage['ai-web-push-debug'] = 'true' to see all events in the console.
Available events
| Event | When it fires | Fields in the dataLayer |
|---|---|---|
ai_web_push_browser_not_supported | Browser doesn't support the notifications API (WebViews, iOS Safari, insecure contexts) | push_provider: ai_web_push, push_source: native_prompt |
ai_web_push_modal_shown | Custom modal was displayed | push_provider: ai_web_push, push_source: custom_modal |
ai_web_push_modal_accepted | User clicked "Accept" on the custom modal | push_provider: ai_web_push, push_source: custom_modal |
ai_web_push_modal_dismissed | User clicked "Cancel" on the custom modal. It also fires after ai_web_push_permission_denied. Starting with version 1.9.3, it no longer fires when the browser prompt expires or is closed without an answer. | push_provider: ai_web_push, push_source: custom_modal |
ai_web_push_prompt_shown | Notification.requestPermission() was called | push_provider: ai_web_push, push_source: custom_modal or native_prompt |
ai_web_push_permission_granted | User accepted the native prompt | push_provider: ai_web_push, push_source: custom_modal or native_prompt |
ai_web_push_permission_denied | User denied the native prompt. In plugin version 1.9.3 or newer, a prompt that expires or is closed without an answer is not counted here and goes to ai_web_push_permission_timeout. | push_provider: ai_web_push, push_source: custom_modal or native_prompt |
ai_web_push_permission_timeout | The prompt ended without an answer, because it expired or was closed. It is not a denial, and the reader can still accept later. Available starting with plugin version 1.9.3. | push_provider: ai_web_push, push_source: custom_modal or native_prompt |
ai_web_push_subscription_success | FCM token obtained and subscription sent to the server. The event fires when the subscription is sent and does not confirm that the server saved the subscriber. | push_provider: ai_web_push, push_source: custom_modal, native_prompt, site_controls or permission_preexisting |
ai_web_push_subscription_skipped | The browser was already registered with the same token, and the plugin does not send a new subscription. Available starting with plugin version 1.9.3. | push_provider: ai_web_push, push_source: custom_modal, native_prompt, site_controls or permission_preexisting |
ai_web_push_subscription_error | Error obtaining FCM token | push_provider: ai_web_push, push_source: custom_modal, native_prompt, site_controls or permission_preexisting |
Push format in GTM
Each event generates a dataLayer.push in this format:
{
"event": "ai_web_push_<nome_do_evento>",
"push_provider": "ai_web_push",
"push_source": "custom_modal | native_prompt | site_controls | permission_preexisting"
}
How to enable debug mode (without reloading)
In the browser console:
localStorage.setItem('ai-web-push-debug', 'true');
// para desativar:
// localStorage.removeItem('ai-web-push-debug');
With debug mode active, each event shows in the console:
- Event name (
ai_web_push_*) push_sourceand details- Preview of the object sent to the dataLayer
- Timestamp
How to test the scenarios
Unsupported browser (WebView, iOS Safari): Expected: browser_not_supported. The flow ends immediately, with no console errors.
Custom modal, user accepts: Expected: modal_shown → modal_accepted → prompt_shown → permission_granted → subscription_success.
Custom modal, user cancels: Expected: modal_shown → modal_dismissed.
Custom modal, user accepts the modal but denies the prompt: Expected: modal_shown → modal_accepted → prompt_shown → permission_denied → modal_dismissed.
Direct native prompt (Chrome), user accepts: Expected: prompt_shown → permission_granted → subscription_success.
Direct native prompt (Chrome), user denies: Expected: prompt_shown → permission_denied → modal_dismissed.
Direct native prompt on Chrome 155 for Android, the visitor ignores it and the prompt expires, or closes it without answering. Expected from version 1.9.3 on, prompt_shown → permission_timeout, with no permission_denied. The prompt only comes back after the Reshow interval, on another page.
The visitor let the prompt expire and later allowed notifications through the site controls. Expected from version 1.9.3 on, without reloading the page, subscription_success with push_source equal to site_controls. If the same browser was already registered with the same token, subscription_skipped fires.
How to create tags in GTM
Trigger: Custom event = ai_web_push_subscription_success
Useful variables:
push_sourceto segment modal vs. prompt.push_provider(alwaysai_web_push— useful if there are other providers).
Recommended tags:
- GA4: push subscription conversion.
- Google Ads: lead/subscription conversion.
- Facebook Pixel: custom subscription event.
- Hotjar/Clarity: funnel events.
Additional recommended tag: Create a trigger for ai_web_push_browser_not_supported and send it as an event to GA4. This lets you monitor how many visitors access your site on browsers without push support, helping you gauge the real impact and adjust your strategy.
New triggers starting with version 1.9.3. Create a Custom Event trigger for ai_web_push_permission_timeout and send it to GA4 as an event, to separate those who did not decide from those who denied. Do not use ai_web_push_subscription_skipped as a conversion, because it indicates a browser that was already registered. If you use a single trigger with the regular expression ^ai_web_push_.*, as in the tutorial How to create Web Push reports in GA4 via GTM, the new events are already included without any change.
Manual capture (without GTM)
You can listen for events in the browser:
aiWebPushFront.on('subscription_success', (detail) => {
console.log('Nova inscrição via', detail.source);
});
// Detectar navegadores sem suporte:
aiWebPushFront.on('browser_not_supported', (detail) => {
console.log('Navegador não suporta push notifications');
// Exemplo: esconder botão de push, exibir mensagem alternativa
});
Available events: browser_not_supported, modal_shown, modal_accepted, modal_dismissed, prompt_shown, permission_granted, permission_denied, permission_timeout, subscription_success, subscription_skipped, subscription_error.
Best practices
- Use
push_sourceto compare modal vs. native prompt and optimize the journey. - Monitor
subscription_erroras an alert in GTM (conversion drops). - Monitor
browser_not_supportedto understand what percentage of visitors use incompatible browsers and adjust your engagement strategy. - To measure real denials, use
permission_denied. Those who did not decide appear inpermission_timeoutand can still accept later. To compare with the period before version 1.9.3, add the two together. subscription_successmarks when the subscription is sent, not the server confirmation.- Leave debug mode off in production; only enable it for troubleshooting.
Quick reference
- Event prefix:
ai_web_push_... - Provider:
ai_web_push - Debug:
localStorage['ai-web-push-debug']='true' - Total events in the table, 11 starting with version 1.9.3, not counting the WebView exit events (see the table in "Available events")