[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) <rde@odoo.com>
This commit is contained in:
@@ -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': [
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<input t-if='website.plausible_shared_key' type='hidden' class='js_plausible_push' data-event-name='Lead Generation' data-event-params='{"CTA": "Contact Us"}' />
|
||||
</t>
|
||||
</t>
|
||||
</field>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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});
|
||||
},
|
||||
});
|
||||
@@ -116,11 +116,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o_dashboard_visits {
|
||||
.o_box > h2 {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 15px;
|
||||
}
|
||||
.o_dashboard_visits {
|
||||
|
||||
.o_demo_background {
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
<t t-name="website.dashboard_content">
|
||||
<div class="o_website_dashboard_content">
|
||||
<t t-call="website.plausible_content"/>
|
||||
<t t-call="website.google_analytics_content"/>
|
||||
</div>
|
||||
</t>
|
||||
@@ -53,6 +54,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.plausible_content">
|
||||
<div class="row" t-if="widget.groups.website_designer && widget.dashboards_data.plausible_share_url">
|
||||
<div class="col-12 o_box">
|
||||
<h2>Analytics</h2>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="embed-responsive embed-responsive-1by1">
|
||||
<iframe t-att-src='widget.dashboards_data.plausible_share_url' class="embed-responsive-item" frameborder="0" loading="lazy"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div t-name="website.unauthorized_analytics" class="col-12 js_unauthorized_message mb16">
|
||||
<span t-if="reason === 'not_connected'">You need to log in to your Google Account before: </span>
|
||||
|
||||
@@ -282,6 +282,36 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-offset-6 col-lg-6 o_setting_box" id="plausbile_setting">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="has_plausible_shared_key"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="has_plausible_shared_key"/>
|
||||
<div class="text-muted">
|
||||
Use Plausible.io, Simple and privacy-friendly Google Analytics alternative
|
||||
</div>
|
||||
<div class="content-group" attrs="{'invisible': [('has_plausible_shared_key', '=', False)]}">
|
||||
<div class="row mt16">
|
||||
<label class="col-lg-3 o_light_label" string="Shared Link Auth" for="plausible_shared_key"/>
|
||||
<field name="plausible_shared_key"
|
||||
attrs="{'required': [('has_plausible_shared_key', '=', True)]}"/>
|
||||
</div>
|
||||
<div class="row mt16">
|
||||
<label class="col-lg-3 o_light_label" string="Site" for="plausible_site"/>
|
||||
<field name="plausible_site"
|
||||
attrs="{'required': [('has_plausible_shared_key', '=', True)]}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div attrs="{'invisible': [('has_plausible_shared_key', '=', False)]}">
|
||||
<a href="https://www.odoo.com/documentation/master/applications/websites/website/optimize/plausible.html"
|
||||
class="oe_link" target="_blank">
|
||||
<i class="fa fa-arrow-right"/>
|
||||
How to create my Plausible Shared Link
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
@@ -154,6 +154,9 @@
|
||||
gtag('config', '<t t-esc="website.google_analytics_key"/>');
|
||||
</script>
|
||||
</t>
|
||||
<t t-if="website and website.plausible_shared_key and not editable">
|
||||
<script id="plausible_script" name="plausible" defer="defer" t-att-data-domain="website.plausible_site" t-att-src="website._get_plausible_script_url()"></script>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
<!-- Page options -->
|
||||
|
||||
@@ -406,6 +406,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input t-if='website.plausible_shared_key' type='hidden' class='js_plausible_push' data-event-name='Lead Generation' t-attf-data-event-params='{"CTA": "Event Registration"}' />
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1875,6 +1875,7 @@
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_website_sale_confirmation_3"/>
|
||||
</div>
|
||||
<input t-if='website.plausible_shared_key' type='hidden' class='js_plausible_push' data-event-name='Shop' t-attf-data-event-params='{"CTA": "Order Confirmed", "amount": "#{"%3s-%3s" % (max(0, round(order.amount_total/100)*100 - 50), round(order.amount_total/100)*100 + 50)}"}' />
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user