* portal, web_unsplash, website_*
This commit renames the `website.group_website_publisher` into
`website.group_website_restricted_editor`.
While the change in itself might look unuseful, it will help the dev and
tech community figuring which group is related to which feature.
Even internally when we discuss specs, we always have to remind which
group is the restricted editor: the publisher one or the designer one?
While it is probably, after all those years, now anchored in some dev
mind, there is no easy way to directly figure which of those 2 groups is
the restricted editor one.
Note that I myself always got confused about it.
Now, the "Restricted Editor" right will be reflected in its technical
name `group_website_restricted_editor`.
Same as for the "Editor & Designer" which technical name is
`group_website_designer`.
As we would like to have a fully working and ready system in v17 for the
community to be able to build themes easily, removing that dubious part
is a nice to have.
Part-of: odoo/odoo#98200
From [1]:
> Dropped all .badge-* color classes for background utilities
> (e.g., use .bg-primary instead of .badge-primary).
We now have to manage constrast for some badge. It's why we
add 'text-dark' at some point.
Note:
Due to the backport of 'text-bg-#{theme}', we can use this to
avoid to use 'text-dark'.
Ref:
[1] https://getbootstrap.com/docs/5.1/migration/#badges
Task ID: 2766483
Part-of: odoo/odoo#95450
* im_livechat, test_event_full, website_blog, website_crm,
website_event, website_event_track, website_event_track_quiz,
webite_livechat, website_sale
There is 6 main changes in this commit:
1. Using raw SQL Upsert instead of the ORM methods. While raw SQL should
generally be avoided, it makes sense for such a low level behavior which
is impacting every flows.
Indeed, tracking visitors is a generic behavior done on all pages and
controllers. It is important to optimize it to reduce processing time
and SQL Queries.
Benchmark of that change alone:
> Rendering a tracked page improves from ~19.5ms to ~17ms (using `ab`
with 1000 loop) and the requests involved in the tracking process are
reduced from 8 SQL Queries to 3:
- 1 request to upsert the visitor
- 1 request to fetch the visitor data
- 1 request to add the tracking record
2. Adding in that upsert query the `visitor.track` insert, creating both
records in one go, bringing the query count from 3 to 2.
3. Refactoring of the `parent_id` behavior that was introduced in stable
with [1]. The purpose was to keep track of multiple visitor linked to a
same user to merge the tracking together. Especially useful for tracking
a same visitor on different devices (when logged in).
Only one visitor was kept as active, others would be archived and their
tracks would be set/moved to the main partner.
Removing those duplicate visitor was not possible because those archived
duplicated visitor were holding the devices notification push token.
Since [2], those token were moved to their own table, all related to the
main visitor.
We can then now safely remove those duplicate visitors after merging
their track to the main visitor. Thus, the `parent_id` field is no more
useful. Removing it removes a layer of complexity.
Note that thanks to this part, the `active` field can also be removed.
4. Deeper functionnal change, inspired from Plausible: The access_token
is no more stored in a cookie but is the result of a hashing method
based on <IP Adress, User Agent>.
The reason behind that change is that, in an upcoming refactoring,
sessions won't be stored anymore unless absolutely needed (login, add to
cart..). It will also ship a no cookies policy, trying to get rid of all
cookies.
This change is bringing some functional changes:
- Since the IP is included in the hash to generate the token, it means
that:
A. If an anonymous user switch IP (eg from 4G to wifi), it is
considered as a new visitor.
B. If 2 anonymous users with the exact same user agent (same browser,
same browser version, same exact os or phone) are on the same IP,
those will be considered as the same visitor.
- Since the request host is not included in the hash, it means that
visiting a DB from 2 differents URLs (domain and/or ip) on the same
device and same browser will result in a shared visitor.
It shouldn't imply any issue as this is A. not wrong and B. mostly
used for tests.
As all this is only related to non logged in user, it shouldn't be a
real issue as anonymous visitors are not supposed to be meant to be
business critical, even if we use them for "a bit more" than simple
analytics data.
5. The access_token is now replaced by the partner_id once the user logs
in, so:
- We don't need to either search on the partner_id field or the
access_token field (depending if the user is logged in or not), we can
only use the access_token row/field to do both.
- On logout, everything works out of the box as the access_token will be
regenerated since there is no partner_id anymore.
- On login, if an access_token matches the user's partner_id, that
visitor is returned.
If there is no such token, a new visitor is created for that partner_id.
In both 2 cases, tracks are moved to that visitor and the anonymous
visitor is removed.
- We can remove the code that was in charge of checking if the
access_token / visitor cookie was wrong (coming from another user eg,
different user login on same device). Indeed, such collision is not
possible anymore as the access_token automatically match the logged in
user.
- We can remove the code that was in charge of checking if the
access_token / visitor cookie was wrong (coming from a logged in user
while the current visitor is not loggedin). Such collision is not
possible anymore as the access_token is (re)generated as an anonymous
token (hash) when not logged in.
6. There is no more check to prevent a track to be created if there was
already a track for that URL in the last 30 minutes.
While this can easily be re-introduced (one CTE on the upsert), it was
adding ~100ms (from ~20 to ~110ms) to the request on a big database as
Odoo where there is ~100 millions tracks and ~100 millions visitors.
It has been validated that it was not a real issue as it is not
fundamentally wrong. If a visitor visited 20 times a product or a
specific page in that short amount of time, you might want to know that
because the user is most likely interested by it.
Changes (1+2), 3, (4+5) and 6 are all independant from each other and
could have existed on their own.
[1]: https://github.com/odoo/odoo/commit/c6b8a44b970a46dcd87a4e2cb1ad52fa340b209f
[2]: https://github.com/odoo/enterprise/pull/16781/commits/f75090fe8b42484e89e933976e8441d2f5eb9415
task-2867045
closesodoo/odoo#87857
Related: odoo/enterprise#28004
Related: odoo/upgrade#3566
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
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.
closesodoo/odoo#91058
Related: odoo/documentation#2007
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Purpose
=======
Pictures from the digest emails are currently stored on the database
itself, meaning that if the database expires (e.g. after trial expires) all
pictures from previously sent emails won't be visible.
This is an issue since digest tips are meant as a marketing tool to bring
people to Odoo after trying a database.
Digest pictures are now taken from Odoo's server
(https://download.odoocdn.com/digests) so that the pictures will still
be visible after the database has expired.
From this commit onwards, it should not be allowed to change a digest
picture with the same name (to display a gif of a newer version), since
all databases with previous versions would receive pictures of a version
that does not correspond to theirs.
This also means that everyone client's Odoo server will contain pictures
that are never used. This could be fixed if Odoo stored them somewhere
else and didn't make them dependent from the git repository.
Task-2372195
closesodoo/odoo#87343
X-original-commit: 35157677a2a63a2559a72aff21e62e23a3c671a2
Related: odoo/enterprise#25654
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
PURPOSE
Visitors are useful in terms of marketing analysis but they can bloat the
database really quickly if you have a lot of traffic on your website.
This commit aims to relieve the database by fully deleting inactive visitors.
SPECS
On an active website, you can easily reach hundreds or even thousands of
visitors per day.
While active visitors are useful for marketing purposes, inactive ones were
archived after a period of inactivity (i.e: not connected for X days in a row,
where X is configurable as a parameter and 30 by default).
But archiving visitors is not really useful either.
We don't see any specific cases where you would want to restore some visitors.
That means we are better off unlinking the visitors completely to save database
storage space.
We want to make exceptions and avoid deletion of inactive visitors in some
cases:
- When they are linked to a partner (meaning most likely linked to a
registered user)
- When they are linked to leads
- When they are registered to events
Several tests were added to ensure that leads matching these conditions are not
unlinked.
We also took this opportunity to enforce the "_link_to_visitor" rules in those
tests to make sure that:
- When visitors are linked, the leads are merged into the main visitor
- When visitors are linked, the event tickets are merged into the main visitor
- When visitors are linked, the wishlisted tracks are merged into the main
visitor
This is also preliminary work for a commit that will move the push_token of
website.visitors to a separate table.
That will in turn allow us to link the push_tokens within the
"_link_to_visitor" method and delete the linked visitor instead of archiving
it.
LINKS
Task-2410217
Part-of: odoo/odoo#65113
The concept of 'parent_id' on website.visitors was introduced in the saas-13.3
stable while implementing the "event online" feature:
However, it should have been part of the website module from the start since
it's a 'global' concept that does not depend on events at all.
See #53540 for more details.
This commit aims to clean the code by moving the field to the website module,
which allows a nice cleaning of associated overridden methods as well.
Along with that, we move the website.visitor demo data from the event module to
the website module, allowing a fresh install of website to showcase some of our
visitors feature.
We also took this opportunity to do some minor improvements in the visitors
kanban view in order to make relevant information more visible.
Task-2429652
Part-of: odoo/odoo#65113
Before this commit, the behavior disabling the unused snippet assets was put
directly in the autovacuum CRON instead of its own CRON.
That behavior is leading to some perf-issue running the autovacuum cron since
it would take too much time.
Indeed, the code will loop inside as many snippet as it exists, and every time
then perform an SQL Query to get the HTML fields using the snippet.
An improvement will come later to not loop on every snippet anymore.
task-2694120
closesodoo/odoo#79981
X-original-commit: 96ab95d37c9b442a4ccb737fd867ca91ec1c11b6
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
In some case, we know that page will contains dynamic content and that cache
should be ignored.
E.g. as soon as a s_snippet_form will be present in page, we know that we need
the real csrf, and so we cannot use the cached response from another user.
Now, we disable the cache (cache_time=0)
closesodoo/odoo#77935
X-original-commit: 262499a91cc9f2365cf2ff131796d9b61b438f9b
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Add an option in the masonry snippet's allowing to choose among multiple
templates for the snippet layout. The usability of the snippet also has
been reviewed (restrict the ability to control background on deeper
boxes). Also reviewed the bg-200 use on boxes and replaced them with
a preset as otherwise it seems buggy to not be able to remove the
bg-200 by selecting a preset (other than hitting the trash icon in the
colorpicker).
Part of https://github.com/odoo/odoo/pull/67361
task-2463033
closesodoo/odoo#67361
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Co-authored-by: smottet <oms@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
The configurator takes care of the organization of the links to the different
pages. Some links are put in the menu and some are put in the footer. The order
is predefined. If too many links are present in the menu then a sub-menu 'Company'
is created and some links are put in it. For the 'News' and 'Succes Stories' features
a website specific blog is created.
Links have the following order in the menu and are present only if their corresponding
website.configurator.feature has been selected in the configurator excepted for the 'Home'
and 'Contact us' links which are default links:
- 'Home'
- 'Shop'
- 'Event'
- 'Courses'
- 'Services'
- 'Pricing'
- 'Company': if more than 8 links in menu and more than 1 item in this submenu
otherwise the three following links are in the top menu.
- 'News'
- 'Success Stories'
- 'About us'
- 'Appointment'
- 'Contact us'
Links in footer:
- 'Privacy Policy'
- 'Help': if website_helpdesk installed. This is not a website.configurator.feature.
- 'Forum'
Community: https://github.com/odoo/odoo/pull/71993
Enterprise: https://github.com/odoo/enterprise/pull/18930
task-2518565
Co-authored-by: Sébastien Mottet (oms) <oms@odoo.com>
Co-authored-by: Romain Derie <rde@odoo.com>
Co-authored-by: Jeremy Kersten <jke@odoo.com>
- fixed xml data files order, otherwise form field would not be whitelisted,
including `email_to`, so the mail would not be send.
- add the same data-for behavior from website_crm to website, to be able to
prefill a field with an URL param
- removed the fallback data-for in website_crm, the JS in now in charge of
doing that. Plus it was creating a misheavior -> you could have prefill set
to false but still, it would prefill the user info
- fixed the form option so the field.name is not used as field.string if there
is already an explicitely set field.string..
- adapt field name in /contactus form (xml view), form snippet (registry) and
crm form (registry) for more consistence
- added the prefill option set to true by default on /contactus (to fit what
we had before). This came with a change in the test as we don't need to
enable it anymore.
- added also the prefill option to true by default on form snippet
Part of #69888
task-2462993
Before this commit (and the previous ones that prepare it), the contact
us page was largely editable but not entirely. The automatic address
field on the right column prevented the page to be considered like any
other page and only the left column was editable. That led to less
possibilities and difficulties to make a modern contact page.
Now, the whole page is static, like a page the user would have created
himself. Same for the thank you page. This comes with the disadvantage
of having to handle the address by yourself (but that's not a field that
would normally change a lot anyway) and the website_crm app now needs to
be enabled on the form via edit mode after install to change the form
action to lead creations.
Part of https://github.com/odoo/odoo/pull/69888
task-2462993
*: website_crm, website_form_project, website_hr_recruitment,
website_sale
Replace website_crm specific behavior by another option for all website
forms.
Part of https://github.com/odoo/odoo/pull/69888
task-2462993
*: crm_iap_lead_website, website_crm, website_form_project,
website_hr_recruitment, website_sale
Part of https://github.com/odoo/odoo/pull/69888
task-2462993
Rename field website_type_preselection to website_config_preselection since feature
preselection is not only based on website type anymore but also on website purpose.
task-2518565
closesodoo/odoo#73377
Related: odoo/enterprise#19498
Related: odoo/upgrade#2625
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
- Creating a website through the configurator activated the configurator tour.
This tour was active for every websites even the ones not created using the
configurator. Theme tours were overridden by the configurator tour when they
should have been the active tour for website not created using the configurator.
Now the configurator tour is an asset specific to each website. This asset is
deactivated by default and activated for a website only if it is created using
the configurator.
- Some actions of the website tour were also visible when we were not in edit
mode. extra_trigger has been added on these actions to ensure they are visible
only in edit mode.
task-2518565
closesodoo/odoo#72827
X-original-commit: 5799410ec257fc7f756722579d3d0141b0ce7de4
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
- The selection of cards corresponding to already installed modules
is disabled. A disabled style has been applied to these cards and an
info icon added. On hover on this icon the user is informed that the
module is already installed on its DB.
- Modules that were preselected based on website type can now be
unselected by the user.
- Correct typo in description of feature_module_career.
task-2518565
closesodoo/odoo#72688
X-original-commit: ab364b06dbb20cce90c7caa8ca15d034e2dcb25e
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Signed-off-by: Sébastien Mottet <smottet@users.noreply.github.com>
- New and multiples pictures
- Empty URL instead of odoo.com by default
task-2471323
closesodoo/odoo#70528
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit improves the mechanism to find the best URL given a record.
To find the best suited URL, the following heuristic will be done:
- If record has a website_id, use that website's domain
- Else if a record has a company_id, use the company's website's domain [1]
- Else use the `web.base.url` ICP
The following commit will replace (almost) every occurence of ICP by the
`get_base_url()` helper method.
[1] Before this commit, there was no way to know which website was the one from
a company, has a company could have no website but could also have multiple
websites.
We now consider the first found website for a company as the company's
website. The use of a new sequence on `website` will allow user to chose
which website to use.
Community: https://github.com/odoo/odoo/pull/68201
Enterprise: https://github.com/odoo/enterprise/pull/17538
Upgrade: https://github.com/odoo/upgrade/pull/2372
task-2476101
Some feature descriptions and titles have been reworded.
A sentence has been added below the title to indicate
that choices made on this screen are not definitive.
Task ID: 2451965
closesodoo/odoo#70252
X-original-commit: 63195ba03ccc1bf40b4682fc7c9aa4a1a55f1e43
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Signed-off-by: Sébastien Mottet <smottet@users.noreply.github.com>
Rationale:
The majority of cases where an ir.asset is manually declared
outside of manifest files is to specifically add a single asset file.
This means developers are specifying a single asset *path*, and not a
glob expression. In this context, it seems better to name the filepath
field `path`, and document that it can be specified with a glob
expression when (seldom) needed, rather than making the exception appear
to be the norm - possibly puzzling many developers (What's a glob and
why do I need one?)
The doc is updated as well, and some spell-checking and wording
improvements were done too.
This required some adaptations to the existing `ir.asset` declarations:
- odoo/enterprise#17465
- odoo/design-themes#459closesodoo/odoo#68695
Related: odoo/upgrade#2348
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
On website app installation and on new website creation a configurator is launched.
The purpose of this configurator is to generate a website that meet the user's needs.
The configurator is composed of 4 steps:
1) Business description: the user is asked to describe its need with its website purpose (dropdown), its industry (autocomplete search) and its objective (dropdown).
2) Logo and palette selection: the user must select a color palette for its website. He can also upload its logo. In this case color palettes recommendations are generated based on the logo's colors.
3) Features selection: the user select the pages and applications he needs.
4) Theme selection: three themes are recommended to the user based on its industry. This screen display a preview of these three themes.
task-id: 2451965
ENT PR: odoo/enterprise#16949
UPG PR: odoo/upgrade#2316closesodoo/odoo#67537
Signed-off-by: Sébastien Mottet <smottet@users.noreply.github.com>
Conversion of all modules to the new manifest assets declaration.
Part of task: 2352566
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Simon Genin <ges@odoo.com>
Before this commit the recently viewed products were handled differently
from the dynamic product snippet.
After this commit the dynamic product snippet supports the functionality
of the recently viewed products snippet:
- its template used to show each product
- its filter of displayed products
- its "Add to cart" feature (with the animation)
- its "Forget" feature (only applicable when viewing recently viewed)
Also added "Accessories" and "Recently Sold With" filterings.
Several kinds of filtering can be combined.
- Products can be restricted to a given category
- Pseudo categories for all products or current category can be used
- Products can be restricted to matching names
- Products can be obtained from one of the following:
- Newest
- Latest sold: ordered by descending frequency in last 8 orders
- Latest viewed
- Accessories (of the current product)
- Recently sold with (the current product)
Accessories and recently sold with are only available in product pages.
Also, generic templates have been considered useless and the whole
mechanism allowing them has been removed (this includes the
pre-rendering mechanism for the fields specified in the filter).
task-2453416
https://github.com/odoo/odoo/pull/65554
Call _get_filter_meta_data when needed instead to compute it only once and
give it from function to function, it is really trivial to compute and the
api of functions are simple from this way.
Avoid to use h4/h5 taf for styling bug use bootstrap feature for it.
The semantic of <div class='h4'/> vs <h4/> is not the same for SEO
Don't make call_to_action_url required
+ small typo
task-2446024
https://github.com/odoo/odoo/pull/65176
Before this commit the filtering code for the Dynamic Products snippet
was rendering all its values.
After this commit the filtering code for the Dynamic Products snippet
mostly returns the values to be rendered.
Because the list_price still needs to be rendered with the correct
currency, the general rendering mechanism is being informed through the
field meta-data that the escaping was already done.
task-2446024
https://github.com/odoo/odoo/pull/65176
Before this commit when a dynamic snippet was fully configured but
returned no data, the rendered section remained empty in edit mode.
After this commit when a dynamic snippet is fully configured but has no
data to display, some sample data is generated in edit mode to give a
feel of how the page will look like when data will be available.
task-2446024
https://github.com/odoo/odoo/pull/65176
Before this commit, the page can be set in cache with some data pre-filled.
Now we don't cache anymore the contactus page if you have GET params.
closesodoo/odoo#65608
X-original-commit: 4ce59c3ab26a441ad8b7f2fd038b690cf897231d
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commits adds a few digest tips concerning the website
customization and shortcuts in timesheet. It also changes
sequence of one.
Add css selectors to include button inside the digest tips,
matching existing style: no underline, white text on odoo
purple button.
PR #63784
Task-2341722
Related: odoo/enterprise#15478
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Homepage tour starts with a very generic step 'drop snippet'
So, you can be in the middle of another tour and see the step of homepage tour.
This doesn't fix all cases, but make conflict less frequent.
E.g.
go to step 4 of tour event
click on save (before doing the step 5)
click on edit
Element is no more dirty (because save before step 5) so the step 5 not visible,
Tour with higher sequence (== lower priority) become visible. (e.g.: homepage)
Forward-Port of bca6cf2693d38c76b1af08398a3125bb16b59c15
closesodoo/odoo#61157
Related: odoo/design-themes#416
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Made the website_id non mandatory on website snippet filters and adapted
the fetching route so that it interprets an unspecified website_id as
the filter being available on any website.
Before this commit website snippet filters had to be limited to one
single website.
After this commit website snippet filters can be made available on all
websites by setting their website_id to no value (this is the new
default of the pre-defined filters).
https://github.com/odoo/odoo/pull/59831
task-2355369
closesodoo/odoo#59831
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Issue
To do on Community:
- Install website_sale (eCommerce)
- Go into Website app
- Navigate through Product/Products
- Edit 'Customizable Desk (CONFIG)' and add '&' and/or '<' and/or '>'
characters into the name
- Save
- Go to the Website app Dashboard and click on 'Go to Website'
- Click on 'Edit' button
- Drag and drop the 'Dynamic Product' snippet into the website
- Click on the block 'Your Dynamic Snippet wil be ...'
- In the right panel, in the 'Dynamic Product' snippet options,
chose a 'Template' and a 'Product Category'
A traceback is shown
Cause
the '&' character crashes lxml.etree.fromstring
Solution
ensure no '&' is sent to lxmx.etree.fromstring by using
odoo.tools.html_escape (in order to ensure no other problematic
characters are sent to the front) on the field values except when
not applicable (widget rendering with record_to_html should not be
escaped).
It is important to note here that this is applicable
to action servers that are used by the dynamic filter.
opw-2357027
closesodoo/odoo#59805
X-original-commit: f91422115c09be484f2868347566b6392ed0effd
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
And other reported English mistakes in source string
Courtesy of Transifex translators
And remove leftover from gengo
closesodoo/odoo#59022
X-original-commit: 26efc84c5cac47a2cc83d7b084f8b71528fec6c7
Related: odoo/enterprise#13781
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
* Prior to this commit, images were only managed when being an image
field. No widget were used either.
* After this commit, image stored in model as url (as res.country.image_url)
can be used when specifying ':image' after the field name. The fields are
now rendered using their corresponding default widget. If there is a need
to force another widget and if the developer is sure that it is compatible,
he/she can specify it using the notation: 'field_name:widget_name'.
closesodoo/odoo#57645
X-original-commit: 18d4e3327c7152b4c3a86ba377e3357f213b703c
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Storing attachment in database (when not specified as an url attachment) copies
the given file in the filestore. When not necessary, this should be avoided to reduce
the databases footprint (and their backups).
On a given instance, the gain is minor, but on servers with hundreds of databases and/or
backups, the impact is noticeable, leading to an economy of scale.
* Implement new snippets that allow the user to choose a filter
and a template.
Three snippets have been created:
- Dynamic Snippet: Displays the data in a grid format
- Dynamic Carousel: Displays the date in a carousel
- Dynamic Products: Let the user pick a product category and
displays the products in a carousel
task-2276740
PR #53175
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
PURPOSE
Review the tips and digest layout design to make sure they have a WOW effect
and increase trial conversion/retention.
SPECIFICATIONS
“Engage with visitors to convert them into leads”
“Use royalty-free photos”
“Search Engine Optimization (SEO)”
See code for specifications.
LINKS
Task ID-2274264
COM PR: odoo/odoo#53580
ENT PR: odoo/enterprise#1139
X-original-commit: b78921d41ca1af3e56a4d874381c30d766c986fc