Hey, I've been working on an overhaul for the dashboard:
Here's a summary of some of the things I've worked on, the biggest changes are that I removed the react app in favor of vanilla JS (no more building of React app) and I've implemented more graphs and widgets, along with a way to turn them on or off.
If you're interested I can make a fork & merge request?
Anyway, these are some of the changes:
Complete Widget Implementation
- Implemented all 18 analytics widgets (previously only 3 were functional):
- Overview metrics (Visitors, Page Views, Bounce Rate, etc.)
- Time-based charts (Visitors Over Time, Page Views Over Time)
- Device & Browser analytics
- Top Pages, Geography, Traffic Sources
- Downloads, Custom Events, Search Behavior
- Page Behavior, Performance, Sessions
- Social Media, E-commerce, Goals
- Content Tracking, Consent, Google Ads
Widget Visibility Control
- Widgets now only display when both conditions are met:
- Widget is enabled in dashboard settings
- Widget has data available from the API
- Empty state message shown when no widgets are enabled
Piwik PRO Report Links
- Added direct links to Piwik PRO reports for all 18 widgets
- Main "View full analytics" link in dashboard header
- Individual "View report →" links for each widget
- All links use correct URL structure:
{base_url}/analytics/#/{website_id}/reports/{path}/ - Opens in new tab for seamless workflow
Local Chart.js Support
- Added automatic detection for locally installed Chart.js library
- Fallback to CDN when local library not available
- Implemented
hook_library_info_alter()for smart detection - Checks multiple common installation paths:
libraries/chart.js/dist/chart.umd.min.js(Composer via asset-packagist)libraries/chartjs/dist/chart.umd.min.jslibraries/Chart.js/dist/chart.umd.min.js
Technical Details
- Vanilla JavaScript implementation (CSP-compliant, no frameworks)
- Chart.js 4.4.0 for data visualizations
- Proper widget enable/disable logic using
isEnabled()checks - Responsive grid layout with mobile optimization
- Custom domain support (e.g., statistiek.rijksoverheid.nl)


| Comment | File | Size | Author |
|---|---|---|---|
| Screenshot 2025-12-01 at 21-02-05 Piwik PRO Dashboard .png | 1.12 MB | immoreel | |
| Screenshot 2025-12-01 at 21-02-44 Piwik PRO Dashboard Settings.png | 515.77 KB | immoreel |
Issue fork piwik_pro-3560912
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
immoreel commentedOk, I've made a merge request with changes as stated above, can someone test this?
Comment #4
immoreel commentedComment #5
hartsak commentedHello @immoreel!
Thanks for your contributions!
We'll check it out.
Comment #6
hartsak commentedHey there @immoreel!
I''m very sorry about my delayed reply.
Apparently, I had already written a comment but got interrupted and then I lost my message!
Anyway, we took a look at your dashboard solution some time ago with @joonaskokko and we think it's really cool! Thank you for your work with it.
I think it's the right way to go with the javascript implementation. Originally the point of having that separate app was that the same dashboard could be more easily implemented to other CMS platforms too, like Wordpress and the like.
Now that the app is already done and released, I guess we could move on and start working towards a "vanilla" solution, like you have proposed! Your version brings a lot of new features and widgets compared to the react app.
However, what we would like to see is that the html markup and styling would be separated from the javascript code and moved to templates/theming side.
Another thing was that the code now has /nl prefixes included in some of the paths/urls, so those need to be fixed.
I'll move this to "needs work" for now.
Comment #7
immoreel commentedChanges in this update:
Bug fixes:
- Fixed fetchToPages() typo → fetchTopPages()
- Added missing 1d (Last24Hours) case to DateRange enum - previously 1d range fell back to 7d
- Secured /api/piwik-dashboard/config endpoint with permission check (was publicly accessible)
Code quality improvements:
- Added calculatePastDate() helper method to reduce code duplication in PiwikApiClient
- Made CORS headers conditional (only active in DDEV/development environments)
- Completed config schema with enabled_widgets_high, enabled_widgets_medium, enabled_widgets_lower fields
Frontend refactoring:
- Moved HTML markup from JavaScript to Twig templates using elements (#tpl-stat-widget,
#tpl-stat-item, #tpl-list-item)
- Removed escapeHtml() function (no longer needed when using textContent)
- Changed hardcoded nl-NL locale to dynamic locale from drupalSettings.path.currentLanguage
- API calls now use basePath with pathPrefix for correct language prefix handling
Comment #8
immoreel commentedComment #9
joonaskokko commentedThis looks really good! We will test this as soon as possible to get it merged 🙂 it will be a good base for further development.
Comment #10
immoreel commentedgreat, if any changes need to be done, let me know!
Comment #11
joonaskokko commentedWe looked the code and it's all good. However, it gives a merge conflict currently. Can you check that?
Comment #12
immoreel commentedsure!
Comment #13
hartsak commentedThanks for everyone! I'll mark this as Fixed now.