Google Analytics can show which pages attract visitors and how traffic changes over time. Turning those numbers into a short explanation still takes work. A local AI assistant can help administrators summarize a report, identify points worth investigating, and ask follow-up questions without leaving Drupal.
This guide explains an implementation that combines the Google Analytics 4 Data API, a custom Drupal dashboard, and Ollama. It covers the data flow, model requests, and permissions needed to keep the assistant private. See Set Up Local AI with Ollama for the inference setup; a second GPU computer is optional.
What does the analytics assistant do?
The dashboard presents analytics figures alongside a generated summary, highlights, and cautious recommendations. A separate assistant form lets an administrator ask questions about the selected reporting period.
For example:
- “Which of the supplied top pages received the most views?”
- “What does this report show about our traffic sources?”
- “What should I investigate based on these changes?”
The assistant answers from a prepared aggregate report. It does not browse the web, identify individual visitors, or automatically fetch a different dataset for each question. When a requested metric is missing, the prompt asks the model to explain that limitation.
Why use local AI for analytics?
A summary can help an administrator decide where to look first, especially when several report sections need attention. Hosting inference locally gives you control over the model and the machine interpreting the report.
Google Analytics remains an external service: Google receives the collected events and provides the reporting data. “Local AI” refers to the interpretation step, not to moving the analytics database onto your computer.
The numeric dashboard must work independently of AI. A model can suggest an investigation, but it should not be the authority for totals, percentage calculations, or explanations of causation.
Understand the three parts of the integration
Collection:
Visitor browser -> consent-aware tracking -> Google Analytics
Reporting:
Authorized Drupal user -> GA4 Data API -> aggregate report
Interpretation:
Report and optional admin question -> Ollama -> summary or answer
Our implementation uses the contributed google_tag module and Klaro for browser collection, plus a custom site_analytics module for reporting and AI interpretation. The custom module must be implemented or supplied as project code; enabling Google Tag alone does not create this dashboard.
Step 1: give Drupal read-only access to reports
Create or select a GA4 property that collects the intended site's events. Enable the Google Analytics Data API in Google Cloud, create a service account, and grant that account Viewer access to the GA4 property. Follow the official Data API quickstart.
Keep these identifiers distinct:
| Setting | Purpose |
|---|---|
Measurement ID, such as G-XXXXXXXXXX |
Browser event collection |
| Numeric Property ID | Identifies the property queried by the reporting API |
| Service-account credential | Authenticates server-side report requests |
Our custom integration reads environment settings like these:
GOOGLE_ANALYTICS_MEASUREMENT_ID=G-XXXXXXXXXX
GOOGLE_ANALYTICS_PROPERTY_ID=123456789
GOOGLE_APPLICATION_CREDENTIALS=/var/www/html/private/ga-service-account.json
The values are examples. Store the credential outside Drupal's public web root, keep it out of Git, and grant the PHP process the access needed to read it. For containers, use a path that exists inside the container.
The reporting client authenticates server-side and obtains a short-lived token with the analytics.readonly scope. Neither the browser nor Ollama receives the private key.
Step 2: build a reliable report before adding AI
The report service requests explicit dimensions and metrics, normalizes the results, and calculates comparisons in PHP. Its dashboard includes users, sessions, views, engagement, top pages, countries, traffic sources, and other configured aggregates.
Cache reports to avoid requesting the same data repeatedly. Display the selected period clearly so users know what an answer refers to. A valid response with no rows can mean no processed data is available for that range; it is different from an authentication error.
Only after the dashboard works should the AI layer receive a bounded selection of its report data. This keeps the model's context manageable and gives you a factual result to compare with its explanation.
Step 3: ask Ollama to explain the supplied figures
The AI service serializes selected aggregates as JSON and sends them to /api/chat. Its prompt requests a factual summary, a few highlights, and cautious actions. Page titles and other strings in the report are explicitly treated as data, not instructions.
The requested response has this structure:
{
"summary": "A short explanation of the supplied figures.",
"highlights": ["An observation supported by the report."],
"recommendations": ["An action to consider investigating."]
}
Ollama accepts a JSON schema in the request's format field. Our service defines the expected strings and arrays, uses a low temperature, parses the returned content, and checks for a usable summary. It bounds output and caches successful summaries. See the chat API reference.
The model receives aggregate context, not cookies, IP addresses, raw visitor sessions, credentials, or stored public-chatbot questions. Its interpretation is labelled advisory because a structured response can still contain a mistaken inference.
For example, fewer organic sessions may justify checking landing pages and recent changes. Those figures alone do not prove that a search algorithm update caused the decline. Official totals and comparison calculations remain in the report service.
Step 4: add an administrator question form
The assistant form accepts a question and uses the selected date range to prepare its context. In this implementation, questions are limited to 300 characters. The prompt asks for a short answer using only the supplied report and tells the model to identify missing information.
The flow is straightforward:
Validate the submitted question and selected dates
-> load the aggregate report
-> attach the question to the report context
-> call Ollama
-> parse and display the answer
Unlike the public article chatbot, this assistant does not retrieve article passages. Its evidence is the analytics report. It also does not let the model execute SQL or choose arbitrary API queries.
Generated dashboard summaries are cached. In the current implementation, each submitted assistant question makes its own inference request.
Step 5: enforce administrator-only access
Define permissions in the custom module and require them on the dashboard, assistant, export, and settings routes. For example, the assistant route uses:
site_analytics.assistant:
path: '/admin/reports/site-analytics/assistant'
defaults:
_form: '\Drupal\site_analytics\Form\AnalyticsAssistantForm'
_title: 'Analytics assistant'
requirements:
_permission: 'view site analytics'
methods: [GET, POST]
This route assumes the custom permission and form class exist. Drupal Form API handles form submission and CSRF protection. The /admin path is a naming convention; the permission requirement enforces access.
In our module, dashboard and CSV export also require view site analytics, while settings require administer site analytics. Grant these permissions only to the intended administrator role to make the feature admin-only. Check access as both an anonymous visitor and an ordinary authenticated user.
The configuration page at /admin/config/services/site-analytics provides separate switches for summaries and the assistant. Keep the private reporting interface separate from the public chatbot widget.
Keep AI optional for reporting and alerts
Use finite connection and request timeouts. If inference fails, continue displaying the factual dashboard and show a clear unavailable message for the assistant. A second configured Ollama endpoint can provide optional fallback, but one working local endpoint is enough for the core integration.
Our custom analytics service reads endpoint and model settings from the article-chatbot configuration. It tries the primary and then the secondary on request failure. That reuse is a project design choice; another implementation could store its own AI settings.
Weekly digests can include a generated summary, while anomaly thresholds should be evaluated in code. In this implementation, PHP determines whether a threshold is crossed, and factual email delivery can continue without an AI response.
Verify the complete integration
First test event collection and report authentication independently. Then compare a generated summary with the displayed figures, ask a question the report cannot answer, and test inference failure in development. Confirm unauthorized users cannot open the assistant or export data.
Account for reporting freshness and Drupal caching when investigating stale results. Refreshing Drupal's cache cannot make Google process events sooner. Before deploying the feature, configure the intended environment's credentials, permissions, and any scheduled mail delivery.
The result is a private assistant that helps administrators read and question their reports while preserving the dashboard as the source of verified numbers.