zero1 / module-livechat
LiveChat integration for Magento 2 / Hyvä: deferred widget embed plus product-tab chat drafts
Package info
github.com/zero1limited/module-livechat
Type:magento2-module
pkg:composer/zero1/module-livechat
Requires
- php: >=7.4
- magento/framework: *
- magento/module-catalog: *
- magento/module-checkout: *
- magento/module-config: *
- magento/module-sales: *
- magento/module-store: *
Requires (Dev)
None
Suggests
- magento/module-csp: LiveChat domains are whitelisted via etc/csp_whitelist.xml
Provides
None
Conflicts
None
Replaces
None
README
Integrates LiveChat with Magento 2.4 (Hyvä and Luma).
Installation
composer require zero1/module-livechat bin/magento module:enable Zero1_Livechat bin/magento setup:upgrade
Configuration: Stores › Configuration › Customers › ZERO-1 | LiveChat (default / website / store view scope).
Features
Widget embed
- Paste the Web Widget HTML Code from LiveChat / Text (Settings › Channels › Website › Install manually) into the admin. Because LiveChat change this snippet from time to time, the module outputs their code as-is rather than rebuilding it from a license number. When they update it, paste the new version in.
- The pasted code is split into its
<script>/<noscript>parts. Each script is output throughSecureHtmlRenderer, and comments and any other markup are dropped. Saving fails if no<script>block is found. - Optional group setting.
- Load strategy: on first interaction (scroll / click / key / touch – default, keeps
tracking.jsoff the critical path) or immediately (async). - Separate chat sessions between groups (
chat_between_groups, off by default). - Optional
product_sku/product_namesession variables on product pages. - Skips itself if LiveChat is already on the page (e.g. via GTM), so the widget never loads twice.
- Inline scripts go through
SecureHtmlRenderer; LiveChat hosts are added inetc/csp_whitelist.xml.
Product tab chat drafts
When a customer selects a product info tab (Delivery, Returns, …) the chat input is pre-filled with a configurable message, e.g. "Hi, I have a question about delivery for {product}".
- Hyvä: detects elements whose
@click/x-on:clicksetsactiveTab = '<key>'. - Luma: detects
.product.data.itemstab titles (id="tab-label-<key>"). - Default does not pop the chat open: the draft is applied when the customer next opens chat, or straight away if chat is already open. "Open Chat on Tab Click" changes this.
- Optional
last_tab_viewedsession variable so agents see the context. - Placeholders:
{product},{sku},{tab}. - Works whether the widget is embedded by this module or elsewhere.
Sales tracking
Sends each order to Text Sales Tracker from the order success page (checkout_onepage_success, which Hyvä Checkout also uses):
LiveChatWidget.call('track_sales_event', { name: 'store_order_was_created', data: { order: { ... } } })
- Order:
id/order_number(increment ID),currency(order currency),total_price(grand total),subtotal_price,shipping_price,tax_price,discounts(coupon),sales_channel(store view),status_page_url(customer account orders only). - Line items:
product_id,title,quantity,price(unit price incl. tax),sku,variant_id/variant_title(configurable attributes and custom options),thumbnail_url(optional). - With the "first interaction" load strategy the widget is loaded straight away on the success page, otherwise the event would only be sent if the customer interacted with the page.
- Works whether the widget is embedded by this module or elsewhere (waits up to 10s for
LiveChatWidget). - A sessionStorage guard stops a page reload resending the order. Text also dedupes on their side.
- The store's hostname must be a connected website in your Text account, otherwise Text drops the event.
Google Analytics (dataLayer events)
Text has no GA4 integration for Text accounts (their FAQ points to Playbook webhooks), and the old LiveChat Marketplace "Google Analytics" app sends everything as one LiveChat event. This feature instead listens to the Chat Widget JS API and pushes named events to window.dataLayer, for GA4 tags in Google Tag Manager.
| dataLayer event | When | Extra keys |
|---|---|---|
livechat_opened |
Chat window opened (not the widget restoring its state on page load) | livechat_open_source (visitor / product_tab / incoming_chat), livechat_open_tab |
livechat_chat_started |
Connected to an agent (status chatting). Once per chat |
livechat_chat_id, livechat_thread_id |
livechat_message_sent |
First message the customer wrote. Once per chat | livechat_chat_id, livechat_thread_id |
livechat_form_submitted |
Pre-chat, post-chat or ticket form sent | livechat_form_type (prechat / postchat / ticket), chat IDs |
livechat_chat_rated |
Chat rated | livechat_rating (good / bad), chat IDs |
livechat_chat_rating_cancelled |
Customer removed their rating | chat IDs |
livechat_greeting_displayed |
Greeting shown | livechat_greeting_id |
livechat_greeting_clicked |
Greeting button clicked | livechat_greeting_id |
- Count "users who chatted" on
livechat_message_sent.livechat_chat_startedalso fires when an agent starts a chat with a visitor who is only browsing. - "Once per chat" is keyed on the chat thread and remembered in localStorage, so the same chat isn't counted again on each page view or tab. A chat reopened later (new thread) counts again.
- Without a pre-chat form, the widget sends the customer's first message before the chat exists. That message is reported once the chat is created (status
queued/chatting), with the new thread ID. - On each page load the widget re-adds the chat history as new events. Those are ignored (anything before the widget's
readycallback or older than the page). livechat_open_source:product_tab= opened by "Open Chat on Tab Click" (with the tab key inlivechat_open_tab),incoming_chat= the widget opened itself because an agent started a chat,visitor= everything else.- Every push resets the other
livechat_*keys, so one GA4 event tag on a^livechat_trigger never picks up a value from an earlier event. Keep that tag separate from the Yireo ecommerce tag, without "Send Ecommerce data". - Optional Send GA Client ID to Chat: reads the GA client ID from the
_gacookie and adds it to the chat as thega_client_idsession variable. Only when the visitor opens the chat, submits the pre-chat form or starts chatting, and only with Cookiebot "Statistics" consent where Cookiebot is on the page. - Works whether the widget is embedded by this module or elsewhere (waits up to 2 minutes for
LiveChatWidget). - GA4 tags, triggers and the "users who chatted" user property are set up in GTM, not here.
Upgrading from 1.x
Nothing breaks on upgrade. enable and license_code keep their 1.x config paths. A saved license number is still used, shown as Legacy License Number, but only while Web Widget HTML Code is empty. The default load strategy matches 1.x (load on first interaction). The frontend block keeps the name zero1.livechat.loader, so theme layout overrides that reference it still apply.
Recommended: paste the Web Widget HTML Code, then clear the legacy license number.
How deferred loading works with the pasted code
The official snippet only calls init() when window.__lc.asyncInit is not set. The module sets asyncInit before the snippet runs, then calls LiveChatWidget.init() on the visitor's first interaction. If LiveChat ever stops honouring asyncInit, the widget will still load, just immediately. The module also checks for an existing tracking.js script, so the widget is never loaded twice.
Changes:
Block\Loaderandview/frontend/web/js/livechat.jsare removed; the loader is now an inline template using a view model.- Requires PHP 7.4+.
Sign up for a LiveChat free 30 day trial.