Google Analytics Plugin for dotCMS - Setup Guide

OSGi plugin that integrates Google Analytics Data API (GA4) with dotCMS, allowing you to fetch analytics data programmatically using Velocity viewtools.

What It Does#


This plugin provides a $analytics viewtool in Velocity templates that lets you query Google Analytics 4 (GA4) data directly from your dotCMS pages. You can retrieve metrics like active users, page views, sessions, and more, filtered by dimensions like date, page path, device category, etc.

Note: This plugin is for fetching analytics data from Google Analytics into dotCMS. It does NOT add tracking code to your site. For tracking, use Google Tag Manager or add the GA4 tracking script directly to your templates.

Prerequisites#


Before installing this plugin, you need:

  1. dotCMS 23.01.10 or higher
  2. Google Cloud Platform account with billing enabled
  3. Google Analytics 4 (GA4) property with data to query
  4. Service account JSON credentials from Google Cloud

Google Cloud Platform Setup#


Step 1: Create or Select a Project#

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one that should have access to your GA4 data
  3. Make sure billing is enabled for the project

Step 2: Enable Google Analytics Data API#

  1. In Google Cloud Console, go to APIs & Services → Library
  2. Search for "Google Analytics Data API"
  3. Click on it and click Enable
  4. Wait for the API to be enabled (takes a few seconds)

Step 3: Create a Service Account#

  1. Go to IAM & Admin → Service Accounts
  2. Click Create Service Account
  3. Fill in the details:
    • Service account name: dotcms-analytics (or any name you prefer)
    • Service account description: "Service account for dotCMS to access GA4 data"
  4. Click Create and Continue
  5. Skip the optional "Grant this service account access to project" step (click Continue)
  6. Skip the "Grant users access to this service account" step (click Done)

Step 4: Create and Download JSON Key File#

  1. In the Service Accounts list, click on the service account you just created
  2. Go to the Keys tab
  3. Click Add Key → Create new key
  4. Select JSON as the key type
  5. Click Create
  6. A JSON file will be downloaded to your computer - save this file securely
  7. Copy the service account email (looks like dotcms-analytics@your-project-id.iam.gserviceaccount.com) - you'll need this for the next step

Google Analytics Setup#


Grant Service Account Access to GA4 Property#

  1. Go to Google Analytics
  2. Click Admin (gear icon in bottom left)
  3. In the Property column, click Property Access Management
  4. Click the + button in the top right
  5. Click Add users
  6. Paste the service account email from Step 4 above
  7. Assign the Viewer role (this gives read-only access to analytics data)
  8. Uncheck "Notify new users by email" (service accounts don't have email)
  9. Click Add

Get Your GA4 Property ID#

  1. Still in Google Analytics Admin, click Property Settings
  2. Look for Property ID at the top (it's a number like 123456789)
  3. Copy this number - you'll use it in Velocity as properties/YOUR_PROPERTY_ID

Installation#


Step 1: Build the Plugin (or Download Release)#

Option A: Download pre-built JAR (when available)

Option B: Build from source

git clone https://github.com/dotCMS/google-analytics.git
cd google-analytics
./gradlew jar

The JAR will be at build/libs/google-analytics-0.4.1.jar

Step 2: Upload to dotCMS#

  1. Log into your dotCMS instance as an admin
  2. Go to System → Dynamic Plugins (or Dev Tools → Plugins depending on your version)
  3. Click Upload Plugin
  4. Select the google-analytics-0.4.1.jar file
  5. Wait for the upload and installation to complete
  6. Check the dotCMS logs for the message: Starting Google Analytics OSGI plugin

If successful, the plugin is now installed.

Configuration#


Configure the Google Analytics App in dotCMS#

  1. Go to System → Apps
  2. Find Google Analytics in the list of available apps
  3. Click on it to configure
  4. Fill in the configuration:
    • Application Name: Any descriptive name (e.g., "My GA4 Property")
    • Json Key File:
      • Open the JSON key file you downloaded from Google Cloud
      • Copy the entire contents of the file
      • Paste it into this field
  5. Click Save

The app is now configured and ready to use.

Usage#


Using the $analytics Viewtool#

The plugin provides a $analytics viewtool in Velocity templates with two main methods:

1. Create an Analytics Request#

#set($propertyId = "properties/123456789")  ## Replace with your GA4 Property ID
#set($request = $analytics.createAnalyticsRequest($propertyId))

2. Configure the Request#

Set date range, metrics, and dimensions:

## Set date range (YYYY-MM-DD format)
$gaRequest.setStartDate("2026-02-09")
$gaRequest.setEndDate("2026-02-16")

## Set metrics (comma-separated) - REQUIRED for GA4
$gaRequest.setMetrics("activeUsers,sessions")

## Set dimensions (optional, comma-separated)
$gaRequest.setDimensions("date,pagePath")

## Set filters (optional)
$gaRequest.setFilters("pagePath==/products")

## Set max results (optional, default: 1000, max: 10000)
$gaRequest.setMaxResults(100)

3. Execute the Query#

#set($gaResponse = $analytics.query($gaRequest))

4. Process the Response#

The response is a RunReportResponse object from the Google Analytics Data API:

## Get row count
<p>Total rows: $gaResponse.getRowCount()</p>

## Iterate through rows
#foreach($row in $gaResponse.getRowsList())
  <p>
    Date: $row.getDimensionValues(0).getValue()
    Active Users: $row.getMetricValues(0).getValue()
  </p>
#end

IMPORTANT: Always use unique variable names like $gaRequest and $gaResponse instead of $request and $response, which are reserved Velocity variables for HTTP request/response objects.

Complete Example#

<h2>Last 7 Days Analytics</h2>

## Your GA4 property ID (just the number, not "properties/123")
#set($propertyId = "123456789")

## Create request
#set($gaRequest = $analytics.createAnalyticsRequest($propertyId))

## Configure request
$gaRequest.setStartDate("2026-02-09")
$gaRequest.setEndDate("2026-02-16")
$gaRequest.setMetrics("activeUsers,sessions")
$gaRequest.setDimensions("date")

## Execute query
#set($gaResponse = $analytics.query($gaRequest))

## Display results
<table>
  <thead>
    <tr>
      <th>Date</th>
      <th>Active Users</th>
      <th>Sessions</th>
    </tr>
  </thead>
  <tbody>
    #foreach($row in $gaResponse.getRowsList())
    <tr>
      <td>$row.getDimensionValues(0).getValue()</td>
      <td>$row.getMetricValues(0).getValue()</td>
      <td>$row.getMetricValues(1).getValue()</td>
    </tr>
    #end
  </tbody>
</table>

Available Metrics and Dimensions#


Refer to the Google Analytics Data API documentation for the full list of available metrics and dimensions.

Common Metrics#

  • activeUsers - Number of distinct users who visited your site
  • sessions - Number of sessions
  • pageviews - Total number of page views
  • screenPageViews - Total page and screen views
  • bounceRate - Percentage of single-page sessions
  • averageSessionDuration - Average duration of sessions in seconds

Common Dimensions#

  • date - Date in YYYYMMDD format
  • pagePath - Page path (e.g., /products/item-1)
  • country - User's country
  • deviceCategory - Device type (desktop, mobile, tablet)
  • browser - Browser name
  • operatingSystem - Operating system name

Troubleshooting#


OSGi Bundle Resolution Errors#

If you see errors like:

Unable to resolve google-analytics: missing requirement osgi.wiring.package; com.aayushatharva.brotli4j
Unable to resolve google-analytics: missing requirement osgi.wiring.package; com.github.luben.zstd
Unable to resolve google-analytics: missing requirement osgi.wiring.package; com.jcraft.jzlib

Cause: The Google Analytics Data API library has many transitive dependencies (compression libraries, gRPC, Netty, etc.) that conflict with OSGi bundle wiring.

Solution: This has been fixed in version 0.4.1 by excluding all third-party packages from OSGi imports (they're bundled inside the JAR instead). Make sure you're using the latest build from the repository.

If building from source: The build.gradle has been updated with proper Import-Package exclusions. If you're using an older version of the repo, pull the latest changes.

Activator Start Error: NoClassDefFoundError: org.apache.velocity.tools.view.ToolInfo#

If you see:

Activator start error in bundle google-analytics
Caused by: java.lang.NoClassDefFoundError: org/apache/velocity/tools/view/ToolInfo

Cause: The plugin's OSGi Import-Package configuration is missing Velocity tool imports.

Solution: This has been fixed in version 0.4.1. The org.apache.velocity.* packages are now properly imported from dotCMS. Use the latest build.

Plugin won't install#

  • Check dotCMS version is 23.01.10 or higher
  • Check dotCMS logs at tomcat/webapps/ROOT/dotsecure/logs/dotcms.log for detailed error messages
  • If using Docker/local install, the OSGi framework may be more strict about dependency resolution than cloud/demo instances

$analytics viewtool not available#

  • Verify plugin installed successfully (check logs for "Starting Google Analytics OSGI plugin")
  • Restart dotCMS after plugin installation
  • Check that the viewtool is registered in the Velocity toolbox
  • Try accessing through toolbox: #set($gaTool = $veltools.get("analytics"))

"App not configured" error#

  • Make sure you configured the Google Analytics app in System → Apps
  • Verify the JSON key file was pasted completely (it should start with { and end with })
  • Check that the Application Name was filled in

"Permission denied" or "403" errors#

  • Verify the service account email was added to GA4 Property Access Management
  • Verify the service account has "Viewer" role
  • Check that the Property ID is correct (format: properties/123456789)

No data returned#

  • Verify your GA4 property has data for the date range you're querying
  • Check that the Property ID is correct
  • Verify metrics and dimensions are valid (see Google Analytics Data API docs)
  • Try querying a broader date range

Error: "Field ga:visits is not a valid metric"#

If you see:

INVALID_ARGUMENT: Field ga:visits is not a valid metric

Cause: The plugin defaults to ga:visits which is a Universal Analytics (GA3) metric. GA4 uses different metric names.

Solution: Always explicitly set metrics using setMetrics() with GA4 metric names:

$gaRequest.setMetrics("activeUsers")  ## GA4 metric
## NOT: ga:visits (old GA3 metric)

See the GA4 API Schema for valid GA4 metrics.

Variable name conflicts: $request or $response showing wrong class#

If $request shows VelocityRequestWrapper or $response shows UrlRewriteWrappedResponse:

Cause: $request and $response are reserved Velocity variables for HTTP request/response objects.

Solution: Use unique variable names:

#set($gaRequest = $analytics.createAnalyticsRequest($propertyId))  ## NOT $request
#set($gaResponse = $analytics.query($gaRequest))  ## NOT $response

Wrong data or unexpected results#

  • Double-check your metric and dimension names match the GA4 Data API schema
  • Verify your filters are correctly formatted
  • Check the date range is what you expect
  • Make sure you're using the property ID as just the number (e.g., "123456789"), not "properties/123456789" (the plugin adds the prefix automatically)

Version History#


  • 0.4.1 - Current version
    • Uses Google Analytics Data API v1beta
    • Compatible with dotCMS 23.01.10+
    • Supports GA4 properties

Resources#


Developer Notes#


OSGi Import-Package Configuration#

The plugin uses a whitelist approach for OSGi Import-Package to avoid dependency conflicts. The build.gradle explicitly imports only what's needed from dotCMS and the JVM:

'Import-Package': '''
    !com.google.*,
    !com.aayushatharva.*,
    !com.github.luben.*,
    !com.jcraft.*,
    !com.ning.*,
    !io.netty.*,
    !io.grpc.*,
    !io.perfmark.*,
    !io.opencensus.*,
    !org.conscrypt.*,
    !org.codehaus.*,
    !org.checkerframework.*,
    !org.threeten.*,
    javax.*,
    org.osgi.*,
    org.apache.commons.io.*,
    org.apache.felix.*,
    org.apache.logging.log4j.*,
    org.apache.velocity.*,
    com.dotcms.*,
    com.dotmarketing.*,
    com.liferay.*
'''

All Google Analytics Data API dependencies (gRPC, Protobuf, compression libraries, etc.) are bundled inside the plugin JAR via the Bundle-ClassPath mechanism.

Building from Source#

If you need to modify the plugin:

  1. Clone the repository
  2. Make your changes
  3. Build with ./gradlew clean jar
  4. The JAR will be in build/libs/google-analytics-0.4.1.jar
  5. Test in a local dotCMS instance before releasing

Plugin Enhancements#

Core dotCMS Integration#

  • Auto-inject Tracking Code: dotCMS/core#34667 - Automatically inject Google Analytics tracking code into pages

Next Steps#


This guide will be used as the basis for:

  1. README.md in the google-analytics GitHub repo
  2. Integration page content on dotcms.com
  3. Updated documentation on dev.dotcms.com/docs
  4. GitHub release with pre-built JAR (no more build-from-source requirement)