Add Google Analytics ViewTool with function-style API and optional tracking ID override#34667
Draft
Add Google Analytics ViewTool with function-style API and optional tracking ID override#34667
Conversation
…ceptor - Created GoogleAnalyticsWebInterceptor to automatically inject GA tracking code - Supports both GA4 (G-XXXXXXXXXX) and UA (UA-XXXXXXXXXX) formats - Injects before </body> tag for optimal performance - Configuration via GOOGLE_ANALYTICS_AUTO_INJECT environment variable - Skips injection in EDIT_MODE and PREVIEW_MODE - Only processes HTML responses (text/html content type) - Registered interceptor in InterceptorFilter - Added comprehensive unit tests Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Added afterIntercept method to properly finalize response modification - Enhanced GAResponseWrapper with finishResponse method - Improved error handling and logging in response finalization - Follows WebInterceptor best practices for response modification Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Added comprehensive documentation for GA auto-injection feature - Created simple standalone tests that don't require PowerMock - Tests cover GA4/UA format detection, HTML injection logic, edge cases - Documentation covers setup, configuration, troubleshooting, and privacy Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Created IMPLEMENTATION_SUMMARY.md with complete overview - Documents architecture, design decisions, and testing strategy - Includes acceptance criteria status and next steps - Provides support considerations and common questions Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Removed Universal Analytics (UA) script template and logic - Simplified generateTrackingScript to only support GA4 format - Updated all tests to remove UA-specific test cases - Updated documentation to reflect GA4-only support - Added note about UA sunset (July 2023) - Simplified implementation (40+ lines removed) Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add Google Analytics tracking code injection for sites
Implement automatic Google Analytics 4 tracking code injection
Feb 16, 2026
fmontes
requested changes
Feb 16, 2026
IMPLEMENTATION_SUMMARY.md
Outdated
- Removed IMPLEMENTATION_SUMMARY.md (content can be in PR description if needed) - Removed docs/google-analytics-auto-injection.md (not needed in repo) - Addresses review comments from @fmontes Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
wezell
requested changes
Feb 17, 2026
Contributor
wezell
left a comment
There was a problem hiding this comment.
I would go back to the LLM and ask it to use the streaming response, rather than reading in the entire response into memory.
Also, I would add the tracking code to the viewtool and not use auto-inject at all - we have seen the shitshow auto-injecting can create. It is not too much to ask to have people add 1 tag to their template.
- Removed GoogleAnalyticsWebInterceptor and auto-injection mechanism - Removed interceptor registration from InterceptorFilter - Created GoogleAnalyticsTool ViewTool for manual template inclusion - Registered googleAnalytics tool in toolbox.xml with request scope - Added comprehensive unit tests for GoogleAnalyticsTool - Provides $googleAnalytics.trackingCode for Velocity templates Benefits: - Developers have full control over tracking code placement - Can be conditionally included based on user consent - No automatic HTML parsing/modification overhead - More transparent and easier to debug - Addresses concerns about auto-injection approach Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Added GOOGLE_ANALYTICS_VIEWTOOL.md with comprehensive usage guide - Added example-ga-template.vtl showing practical implementation - Includes common patterns, troubleshooting, and migration guide - Documents consent management and GDPR considerations Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Added IMPLEMENTATION_COMPLETE.md summarizing all changes - Documents removed auto-inject vs added ViewTool approach - Shows net reduction of 150 lines (simpler implementation) - Lists all benefits and migration steps Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
Copilot
AI
changed the title
Implement automatic Google Analytics 4 tracking code injection
Replace GA4 auto-injection with ViewTool for explicit template control
Feb 17, 2026
- Changed from property access to method calls: trackingCode()
- Added overloaded trackingCode(String) to accept custom tracking ID
- Kept getTrackingCode() as deprecated for backward compatibility
- Added 8 new test cases for function-style methods
- Tests cover: no params, custom ID, null/empty fallback, different formats
- Total tests: 21 (13 original + 8 new)
Usage:
- Site config: $googleAnalytics.trackingCode()
- Custom ID: $googleAnalytics.trackingCode("G-CUSTOM123")
- Backward compatible: $googleAnalytics.trackingCode still works
Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Updated GOOGLE_ANALYTICS_VIEWTOOL.md with trackingCode() syntax - Added examples for custom tracking ID parameter - Added Pattern 5 (multi-environment) and Pattern 6 (multi-tenant) - Updated example-ga-template.vtl to show both basic and advanced usage - Updated API reference table with new methods - All examples now use function call syntax: trackingCode() - Documented backward compatibility with deprecated getTrackingCode() Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
- Added FUNCTION_STYLE_SUMMARY.md with complete overview - Documents both requirements met: function call and optional parameter - Includes all usage examples and patterns - Shows API reference and backward compatibility - Lists all files modified and test coverage - Migration guide for existing users Co-authored-by: fmontes <751424+fmontes@users.noreply.github.com>
Copilot
AI
changed the title
Replace GA4 auto-injection with ViewTool for explicit template control
Add Google Analytics ViewTool with function-style API and optional tracking ID override
Feb 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed Changes
Implements ViewTool for GA4 tracking code injection in Velocity templates. Replaces previous auto-inject approach per feedback: "We have seen the bad results with auto-injecting."
GoogleAnalyticsToolViewTool registered as$googleAnalyticsintoolbox.xmltrackingCode()reads site'sgoogleAnalyticsfieldtrackingCode(String)accepts custom tracking ID for multi-environment/multi-tenant setupsgetTrackingCode()for backward compatibilityUsage:
Checklist
Additional Info
Why ViewTool over auto-inject:
Backward compatible: Property-style
$googleAnalytics.trackingCodestill works via getter method delegation.Documentation:
GOOGLE_ANALYTICS_VIEWTOOL.md- Usage guide with multi-environment/multi-tenant patternsexample-ga-template.vtl- Working template exampleFUNCTION_STYLE_SUMMARY.md- Implementation summaryScreenshots
N/A - Backend feature, no UI changes
Original prompt
This section details on the original issue you should resolve
<issue_title>Implement Google Analytics tracking code injection for sites</issue_title>
<issue_description>## Description
The
googleAnalyticsfield exists in dotCMS sites (Host content type) but is currently only used for storage. The field is exposed via the REST API (SiteResource,SiteForm,SiteView) but has no functional implementation to automatically inject Google Analytics tracking codes into pages.Current State:
SiteResource.GOOGLE_ANALYTICSconstantProposed Implementation:
Automatically inject Google Analytics (GA4) tracking code into pages when the
googleAnalyticsfield is populated on a site.Acceptance Criteria
googleAnalyticsfield value from current site/host context<head>when field is populatedAdditional Context
Related Files:
dotCMS/src/main/java/com/dotcms/rest/api/v1/site/SiteResource.java:100- Field constantdotCMS/src/main/java/com/dotcms/rest/api/v1/site/SiteHelper.java:328- Field mappingdotCMS/src/main/java/com/dotcms/rest/api/v1/site/SiteForm.java:33- Form bindingdotCMS/src/main/java/com/dotcms/rest/api/v1/site/SiteView.java:28- API responseImplementation Options:
</body>GA4 Tracking Code Example:
Considerations:
<agent_instructions>Make sure you use the environment variable, because some customers might not want this enable by default.</agent_instructions>
Comments on the Issue (you are @copilot in this section)
@fmontes ## 🔧 Technical Implementation DetailsServer-Side HTML Generation & Injection Points
Based on analysis of the dotCMS codebase, here are the key classes and patterns for implementing Google Analytics tracking code injection:
Key Architecture Components
1. WebInterceptor Pattern (Recommended Approach)
The cleanest implementation would use dotCMS's
WebInterceptorsystem, which provides a pluggable way to intercept and modify HTTP responses.Key Interface:
com.dotcms.filters.interceptor.WebInterceptor- Core interface for request/response interceptionExisting Interceptor Examples:
com.dotcms.filters.interceptor.meta.ResponseMetaDataWebInterceptor- Adds headers to responsescom.dotcms.analytics.track.AnalyticsTrackWebInterceptor- Injects analytics tracking (perfect reference!)Registration:
com.dotmarketing.filters.InterceptorFilter- Main filter that manages all web interceptors2. HTML Page Rendering Pipeline
Where HTML pages are actually rendered and assembled:
Core Rendering Classes:
com.dotmarketing.portlets.htmlpageasset.business.render.HTMLPageAssetRenderedAPIImpl- Main page rendering APIcom.dotmarketing.portlets.htmlpageasset.business.render.page.HTMLPageAssetRenderedBuilder- Builds page metadata and HTMLcom.dotmarketing.portlets.htmlpageasset.business.render.page.PageView- Page view object containing rendered HTML3. Request/Response Flow
Main filter chain entry point:
com.dotmarketing.filters.CMSFilter- Primary CMS filter (line 59:doFilter)📋 Recommended Implementation Approach
Option A: WebInterceptor (Cleanest & Most Maintainable)
Create a new class: `com.dotcms...
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.