From cccd6eb01dfca898c75e82550e1960065852bf6e Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 10 May 2022 15:15:29 +0000 Subject: [PATCH] [IMP] website[_event,_sale]: add plausible as Analytics solution This commit add the way to specify the Plausible shared key auth token and the plausible domain on your website to have the Plausible Dashboard integrated in your Website > Dashboard > Analytics menu. Some custom event are already pre-configured as: Push an event 'Shop' on confirmation on ecommerce (with amount bucket +/- 50) Push an event 'Lead Generation' on: 'Thank you' page of contactus Confirmation of subscription for an event From this way, the end user can just add a goal 'Lead Generation' or 'Shop' on Plausible to have the Goal values visible. closes odoo/odoo#91058 Related: odoo/documentation#2007 Signed-off-by: Romain Derie (rde) --- addons/website/__manifest__.py | 1 + addons/website/controllers/backend.py | 1 + addons/website/data/website_data.xml | 1 + addons/website/models/res_config_settings.py | 39 ++++++++++++++++++- addons/website/models/website.py | 19 +++++++++ addons/website/static/src/js/plausible.js | 32 +++++++++++++++ .../static/src/scss/website.backend.scss | 8 ++-- .../static/src/xml/website.backend.xml | 15 +++++++ .../views/res_config_settings_views.xml | 30 ++++++++++++++ addons/website/views/website_templates.xml | 3 ++ .../event_templates_page_registration.xml | 1 + addons/website_sale/views/templates.xml | 1 + 12 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 addons/website/static/src/js/plausible.js diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py index a910a2d7c6f..9dbd274884a 100644 --- a/addons/website/__manifest__.py +++ b/addons/website/__manifest__.py @@ -134,6 +134,7 @@ 'website/static/src/js/menu/navbar.js', 'website/static/src/js/show_password.js', 'website/static/src/js/post_link.js', + 'website/static/src/js/plausible.js', 'website/static/src/js/user_custom_javascript.js', ], 'web.assets_frontend_minimal': [ diff --git a/addons/website/controllers/backend.py b/addons/website/controllers/backend.py index 87f9a42eb9a..2022acc97a7 100644 --- a/addons/website/controllers/backend.py +++ b/addons/website/controllers/backend.py @@ -38,6 +38,7 @@ class WebsiteBackend(http.Controller): ga_client_id=current_website.google_management_client_id or '', ga_analytics_key=current_website.google_analytics_key or '', ) + dashboard_data['dashboards']['plausible_share_url'] = current_website._get_plausible_share_url() return dashboard_data @http.route('/website/dashboard/set_ga_data', type='json', auth='user') diff --git a/addons/website/data/website_data.xml b/addons/website/data/website_data.xml index 3502bd06dba..23ce296082a 100644 --- a/addons/website/data/website_data.xml +++ b/addons/website/data/website_data.xml @@ -189,6 +189,7 @@ + diff --git a/addons/website/models/res_config_settings.py b/addons/website/models/res_config_settings.py index 2a7e8d791e9..0f510bffe8f 100644 --- a/addons/website/models/res_config_settings.py +++ b/addons/website/models/res_config_settings.py @@ -6,6 +6,8 @@ from odoo import api, fields, models from odoo.exceptions import UserError from odoo.tools.translate import _ +from werkzeug import urls + class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' @@ -74,7 +76,14 @@ class ResConfigSettings(models.TransientModel): 'Google Search Console', related='website_id.google_search_console', readonly=False) - + plausible_shared_key = fields.Char( + 'Plausible auth Key', + related='website_id.plausible_shared_key', + readonly=False) + plausible_site = fields.Char( + 'Plausible Site (e.g. domain.com)', + related='website_id.plausible_site', + readonly=False) cdn_activated = fields.Boolean( related='website_id.cdn_activated', readonly=False) @@ -118,6 +127,10 @@ class ResConfigSettings(models.TransientModel): "Use a image by default for sharing", compute='_compute_has_default_share_image', inverse='_inverse_has_default_share_image') + has_plausible_shared_key = fields.Boolean( + "Plausible Analytics", + compute='_compute_has_plausible_shared_key', + inverse='_inverse_has_plausible_shared_key') module_website_livechat = fields.Boolean() module_marketing_automation = fields.Boolean() @@ -126,6 +139,18 @@ class ResConfigSettings(models.TransientModel): for config in self: config.shared_user_account = not config.website_id.specific_user_account + @api.onchange('plausible_shared_key') + def _onchange_shared_key(self): + for config in self: + value = config.plausible_shared_key + if value and value.startswith('http'): + try: + url = urls.url_parse(value) + config.plausible_shared_key = urls.url_decode(url.query).get('auth', '') + config.plausible_site = url.path.split('/')[-1] + except Exception: # noqa + pass + def _inverse_shared_user_account(self): for config in self: config.website_id.specific_user_account = not config.shared_user_account @@ -141,6 +166,18 @@ class ResConfigSettings(models.TransientModel): for config in self: config.website_id.auth_signup_uninvited = config.auth_signup_uninvited + @api.depends('website_id') + def _compute_has_plausible_shared_key(self): + for config in self: + config.has_plausible_shared_key = bool(config.plausible_shared_key) + + def _inverse_has_plausible_shared_key(self): + for config in self: + if config.has_plausible_shared_key: + continue + config.plausible_shared_key = False + config.plausible_site = False + @api.depends('website_id') def _compute_has_google_analytics(self): for config in self: diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 595c58c7d50..593275a01f0 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -113,6 +113,9 @@ class Website(models.Model): google_maps_api_key = fields.Char('Google Maps API Key') + plausible_shared_key = fields.Char() + plausible_site = fields.Char() + user_id = fields.Many2one('res.users', string='Public User', required=True) cdn_activated = fields.Boolean('Content Delivery Network (CDN)') cdn_url = fields.Char('CDN Base URL', default='') @@ -731,6 +734,22 @@ class Website(models.Model): page_temp = page_url + (inc and "-%s" % inc or "") return page_temp + def _get_plausible_script_url(self): + return self.env['ir.config_parameter'].sudo().get_param( + 'website.plausible_script', + 'https://plausible.io/js/plausible.js' + ) + + def _get_plausible_server(self): + return self.env['ir.config_parameter'].sudo().get_param( + 'website.plausible_server', + 'https://plausible.io' + ) + + def _get_plausible_share_url(self): + embed_url = f'/share/{self.plausible_site}?auth={self.plausible_shared_key}&embed=true&theme=system' + return self.plausible_shared_key and urls.url_join(self._get_plausible_server(), embed_url) or '' + def get_unique_key(self, string, template_module=False): """ Given a string, return an unique key including module prefix. It will be suffixed by a counter if it already exists to garantee uniqueness. diff --git a/addons/website/static/src/js/plausible.js b/addons/website/static/src/js/plausible.js new file mode 100644 index 00000000000..fa8e3027faf --- /dev/null +++ b/addons/website/static/src/js/plausible.js @@ -0,0 +1,32 @@ +/** @odoo-module **/ + +import publicWidget from 'web.public.widget'; + +publicWidget.registry.o_plausible_push = publicWidget.Widget.extend({ + selector: '.js_plausible_push', + + /** + * @override + */ + start() { + window.plausible = window.plausible || function () { + (window.plausible.q = window.plausible.q || []).push(arguments); + }; + this._push(); + return this._super(...arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Pushes the event `data-event-name` to Plausible with params + * `data-event-params` + */ + _push() { + const evName = this.$el.data('event-name'); + const evParams = this.$el.data('event-params') || {}; + window.plausible(evName, {props: evParams}); + }, +}); diff --git a/addons/website/static/src/scss/website.backend.scss b/addons/website/static/src/scss/website.backend.scss index 1a1a1d7a4c2..874a9a728b4 100644 --- a/addons/website/static/src/scss/website.backend.scss +++ b/addons/website/static/src/scss/website.backend.scss @@ -116,11 +116,11 @@ } } - .o_dashboard_visits { + .o_box > h2 { + padding: 15px; + } - h2 { - padding: 15px; - } + .o_dashboard_visits { .o_demo_background { diff --git a/addons/website/static/src/xml/website.backend.xml b/addons/website/static/src/xml/website.backend.xml index f272f847144..c54f98dd540 100644 --- a/addons/website/static/src/xml/website.backend.xml +++ b/addons/website/static/src/xml/website.backend.xml @@ -29,6 +29,7 @@
+
@@ -53,6 +54,20 @@ + +
+
+

Analytics

+
+
+
+