Liferay Analytics Integrations: Setup Guide | OpsBlu Docs

Liferay Analytics Integrations: Setup Guide

Integrate GA4, GTM, and Meta Pixel with Liferay DXP using theme templates, fragments, and Liferay Analytics Cloud.

Liferay is a Java-based enterprise digital experience platform available as Liferay DXP (commercial) and Liferay Portal (community edition). It uses FreeMarker templates, a fragment-based page builder, and includes Liferay Analytics Cloud as a native analytics module. Analytics integration uses Liferay's theme system, page fragments, or the built-in client extension model (Liferay 7.4+).

Integration Architecture

Liferay provides four integration paths:

  1. Theme Templates -- FreeMarker templates in your Liferay theme control the page HTML structure. Edit portal_normal.ftl (the main page template) to inject tracking scripts globally. Deploy themes as WAR files or as theme modules.
  2. Page Fragments -- Liferay's fragment-based page builder allows custom HTML/CSS/JS fragments. Create a "GTM Container" fragment and add it to page templates or master pages.
  3. Client Extensions (7.4+) -- Liferay 7.4 introduced client extensions that inject CSS/JS globally without modifying themes. Deploy JavaScript client extensions for tracking scripts.
  4. Liferay Analytics Cloud -- Built-in analytics platform that tracks page views, user journeys, and asset interactions. Runs parallel to or replaces third-party analytics.

Available Integrations

Analytics Platforms

Google Analytics 4

  • Theme template injection (FreeMarker)
  • Client extension (Liferay 7.4+)
  • GTM-based GA4 (recommended)
  • Liferay Analytics Cloud (native alternative)

Tag Management

Google Tag Manager

  • Theme portal_normal.ftl injection
  • JavaScript client extension
  • Page fragment with GTM snippet

Marketing Pixels

Meta Pixel

  • Via GTM container (recommended)
  • Theme template or client extension

Theme Template Integration

Edit your theme's portal_normal.ftl to add GTM and a data layer:

<#-- portal_normal.ftl -->
<!DOCTYPE html>
<html class="${root_css_class}" dir="${language_display.dir}" lang="${w3c_language_id}">
<head>
    <!-- Google Tag Manager -->
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;
    j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
    f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-XXXX');</script>

    <script>
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
        'language': '${w3c_language_id}',
        'siteName': '${company_name!""}',
        'pageTitle': '${the_title!""}',
        'isSignedIn': ${is_signed_in?string('true','false')},
        <#if user?? && is_signed_in>
        'userRole': '${user.getRoles()?map(r -> r.getName())?join(",")!""}',
        </#if>
        'layoutType': '${layout.getType()!"portlet"}'
    });
    </script>

    <@liferay.css />
    <@liferay.js />
</head>
<body>
    <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>

    <@liferay.body_top />
    <#-- page content -->
</body>
</html>

Client Extension Approach (Liferay 7.4+)

For Liferay 7.4 and later, create a JavaScript client extension that injects GTM globally without theme modification:

// gtm-client-extension.js
(function() {
  var gtmId = 'GTM-XXXX';
  var script = document.createElement('script');
  script.innerHTML = '(function(w,d,s,l,i){w[l]=w[l]||[];' +
    'w[l].push({"gtm.start":new Date().getTime(),event:"gtm.js"});' +
    'var f=d.getElementsByTagName(s)[0],j=d.createElement(s),' +
    'dl=l!="dataLayer"?"&l="+l:"";j.async=true;' +
    'j.src="https://www.googletagmanager.com/gtm.js?id="+i+dl;' +
    'f.parentNode.insertBefore(j,f);})(window,document,"script","dataLayer","' + gtmId + '");';
  document.head.insertBefore(script, document.head.firstChild);
})();

Deploy via Control Panel > Client Extensions or as an LUFFA (Liferay Unified Frontend Application).

Platform Limitations

Liferay Analytics Cloud overlap. Liferay Analytics Cloud (LAC) tracks page views, asset downloads, form submissions, and user journeys natively. Running LAC alongside GA4 creates parallel data streams. Evaluate whether LAC meets your analytics needs before adding GA4, or disable LAC tracking if using GA4 exclusively.

Theme deployment cycle. Modifying portal_normal.ftl requires rebuilding and redeploying the theme (WAR or module). This follows a formal deployment pipeline and is not a quick configuration change. Client extensions (7.4+) offer a lighter-weight alternative.

Portal caching. Liferay caches page fragments and full pages. Server-rendered data layer values may be cached with the page HTML. User-specific data (role, signed-in state) must use the is_signed_in FreeMarker variable, which is evaluated per-request even in cached pages in some configurations.

SPA navigation (7.x). Liferay 7.x uses SennaJS for SPA-like navigation (partial page updates without full reloads). GTM's standard pageview trigger fires only on initial load. Listen for Liferay's navigation events to track page changes.

Version fragmentation. Liferay 6.x, 7.0-7.3, and 7.4 have different template structures, theme architectures, and extension models. Integration guides must specify the Liferay version.

Performance Considerations

  • Java application overhead. Liferay runs on Tomcat/WildFly/WebLogic with significant baseline resource usage. Tracking script overhead is negligible compared to the platform's own JavaScript and CSS payload.
  • Fragment caching. Liferay caches page fragments. GTM and data layer scripts in cached fragments load without server-side processing overhead.
  • SennaJS interaction. Liferay's SPA framework intercepts page navigations. Tracking scripts must be compatible with partial page updates rather than full page reloads.
  1. Use client extension (7.4+) or theme template for GTM injection
  2. Build FreeMarker data layer -- Use Liferay template variables for page metadata and user context
  3. Handle SPA navigation -- Fire virtual pageview events on Liferay's SennaJS route changes
  4. Evaluate Analytics Cloud -- Determine if it replaces or complements GA4
  5. Configure GA4 via GTM -- Map Liferay layout types and site structures to content groups

Next Steps

For general integration concepts, see the integrations overview.