Merge pull request #20413 from surajshetty3416/website-analytics-enhancements

This commit is contained in:
Suraj Shetty 2023-03-21 11:36:17 +05:30 committed by GitHub
commit 44d4010ea9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 192 additions and 19 deletions

View file

@ -29,6 +29,7 @@
"message",
"message_md",
"message_html",
"campaign",
"attachments",
"send_unsubscribe_link",
"send_webview_link",
@ -237,6 +238,13 @@
"label": "Total Views",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "campaign",
"fieldtype": "Link",
"label": "Campaign",
"options": "Marketing Campaign",
"reqd": 0
}
],
"has_web_view": 1,
@ -245,7 +253,7 @@
"index_web_pages_for_search": 1,
"is_published_field": "published",
"links": [],
"modified": "2023-02-23 12:53:18.478018",
"modified": "2023-03-20 22:45:59.129630",
"modified_by": "Administrator",
"module": "Email",
"name": "Newsletter",
@ -270,4 +278,4 @@
"states": [],
"title_field": "subject",
"track_changes": 1
}
}

View file

@ -167,7 +167,7 @@ class Newsletter(WebsiteGenerator):
attachments = self.get_newsletter_attachments()
sender = self.send_from or frappe.utils.get_formatted_email(self.owner)
args = self.as_dict()
args["message"] = self.get_message()
args["message"] = self.get_message(medium="email")
is_auto_commit_set = bool(frappe.db.auto_commit_on_many_writes)
frappe.db.auto_commit_on_many_writes = not frappe.flags.in_test
@ -193,7 +193,7 @@ class Newsletter(WebsiteGenerator):
frappe.db.auto_commit_on_many_writes = is_auto_commit_set
def get_message(self) -> str:
def get_message(self, medium=None) -> str:
message = self.message
if self.content_type == "Markdown":
message = frappe.utils.md_to_html(self.message_md)
@ -202,9 +202,9 @@ class Newsletter(WebsiteGenerator):
html = frappe.render_template(message, {"doc": self.as_dict()})
return self.add_source(html)
return self.add_source(html, medium=medium)
def add_source(self, html: str) -> str:
def add_source(self, html: str, medium="None") -> str:
"""Add source to the site links in the newsletter content."""
from bs4 import BeautifulSoup
@ -216,8 +216,8 @@ class Newsletter(WebsiteGenerator):
if href and not href.startswith("#"):
if not frappe.utils.is_site_link(href):
continue
new_href = frappe.utils.add_source_to_url(
href, reference_doctype=self.doctype, reference_docname=self.name
new_href = frappe.utils.add_trackers_to_url(
href, source="Newsletter", campaign=self.campaign, medium=medium
)
link["href"] = new_href

View file

@ -36,7 +36,7 @@
</p>
</div>
<div itemprop="articleBody" class="longform blog-text">
{{ doc.get_message() }}
{{ doc.get_message(medium="web_page") }}
</div>
</article>

View file

@ -129,10 +129,10 @@ frappe.ui.toolbar.Toolbar = class {
let awesome_bar = new frappe.search.AwesomeBar();
awesome_bar.setup("#navbar-search");
// TODO: Remove this in v14
frappe.search.utils.make_function_searchable(function () {
frappe.set_route("List", "Client Script");
}, __("Custom Script List"));
frappe.search.utils.make_function_searchable(
frappe.utils.generate_tracking_url,
__("Generate Tracking URL")
);
}
}

View file

@ -1610,4 +1610,65 @@ Object.assign(frappe.utils, {
});
},
},
generate_tracking_url() {
frappe.prompt(
[
{
fieldname: "url",
label: __("Web Page URL"),
fieldtype: "Data",
options: "URL",
reqd: 1,
default: localStorage.getItem("tracker_url:url"),
},
{
fieldname: "source",
label: __("Source"),
fieldtype: "Data",
default: localStorage.getItem("tracker_url:source"),
},
{
fieldname: "campaign",
label: __("Campaign"),
fieldtype: "Link",
ignore_link_validation: 1,
options: "Marketing Campaign",
default: localStorage.getItem("tracker_url:campaign"),
},
{
fieldname: "medium",
label: __("Medium"),
fieldtype: "Data",
default: localStorage.getItem("tracker_url:medium"),
},
],
function (data) {
let url = data.url;
localStorage.setItem("tracker_url:url", data.url);
if (data.source) {
url += "?source=" + data.source;
localStorage.setItem("tracker_url:source", data.source);
}
if (data.campaign) {
url += "&campaign=" + data.campaign;
localStorage.setItem("tracker_url:campaign", data.campaign);
}
if (data.medium) {
url += "&medium=" + data.medium.toLowerCase();
localStorage.setItem("tracker_url:medium", data.medium);
}
frappe.utils.copy_to_clipboard(url);
frappe.msgprint(
__("Tracking URL generated and copied to clipboard") +
": <br>" +
`<a href="${url}">${url.bold()}</a>`,
__("Here's your tracking URL")
);
},
__("Generate Tracking URL")
);
},
});

View file

@ -2256,11 +2256,20 @@ def is_site_link(link: str) -> bool:
return urlparse(link).netloc == urlparse(frappe.utils.get_url()).netloc
def add_source_to_url(url: str, reference_doctype: str, reference_docname: str) -> str:
def add_trackers_to_url(url: str, source: str, campaign: str, medium: str = "email") -> str:
url_parts = list(urlparse(url))
query = dict(parse_qsl(url_parts[4])) | {
"source": f"{reference_doctype} > {reference_docname}",
if url_parts[0] == "mailto":
return url
trackers = {
"source": source,
"medium": medium,
}
if campaign:
trackers["campaign"] = campaign
query = dict(parse_qsl(url_parts[4])) | trackers
url_parts[4] = urlencode(query)
return urlunparse(url_parts)

View file

@ -0,0 +1,64 @@
{
"actions": [],
"autoname": "prompt",
"creation": "2023-03-20 22:36:45.058045",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"campaign_description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "campaign_description",
"fieldtype": "Small Text",
"in_filter": 1,
"in_list_view": 1,
"label": "Campaign Description (Optional)"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-03-20 22:47:25.768582",
"modified_by": "Administrator",
"module": "Website",
"name": "Marketing Campaign",
"naming_rule": "Set by user",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Newsletter Manager",
"share": 1,
"write": 1
},
{
"role": "All",
"select": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View file

@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe Technologies and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class MarketingCampaign(Document):
pass

View file

@ -13,8 +13,10 @@
"is_unique",
"time_zone",
"user_agent",
"visitor_id",
"source"
"source",
"campaign",
"medium",
"visitor_id"
],
"fields": [
{
@ -68,11 +70,23 @@
"fieldtype": "Data",
"label": "Source",
"read_only": 1
},
{
"fieldname": "campaign",
"fieldtype": "Data",
"label": "Campaign",
"read_only": 1
},
{
"fieldname": "medium",
"fieldtype": "Data",
"label": "Medium",
"read_only": 1
}
],
"in_create": 1,
"links": [],
"modified": "2023-02-28 11:55:04.533663",
"modified": "2023-03-20 23:38:27.067285",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Page View",

View file

@ -19,6 +19,8 @@ def make_view_log(
version=None,
user_tz=None,
source=None,
campaign=None,
medium=None,
visitor_id=None,
):
if not is_tracking_enabled():
@ -55,6 +57,8 @@ def make_view_log(
view.user_agent = user_agent
view.is_unique = is_unique
view.source = source
view.campaign = campaign
view.medium = (medium or "").lower()
view.visitor_id = visitor_id
try:

View file

@ -37,6 +37,8 @@ frappe.query_reports["Website Analytics"] = {
{ value: "browser", label: __("Browser") },
{ value: "referrer", label: __("Referrer") },
{ value: "source", label: __("Source") },
{ value: "campaign", label: __("Campaign") },
{ value: "medium", label: __("Medium") },
],
default: "path",
},

View file

@ -33,6 +33,8 @@ ga('send', 'pageview');
version: browser.version,
user_tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
source: query_params.source,
medium: query_params.medium,
campaign: query_params.campaign,
visitor_id: result.visitorId
})
})