mirror of
https://github.com/plausible/analytics.git
synced 2024-12-26 11:02:52 +03:00
119 lines
4.9 KiB
Elixir
119 lines
4.9 KiB
Elixir
defmodule Mix.Tasks.SendEmailReports do
|
|
use Mix.Task
|
|
use Plausible.Repo
|
|
require Logger
|
|
alias Plausible.Stats
|
|
|
|
def run(_args) do
|
|
Application.ensure_all_started(:plausible)
|
|
execute(Timex.now())
|
|
end
|
|
|
|
@doc"""
|
|
The email report should be sent on Monday at 9am according to the timezone
|
|
of the site. This job runs every hour to be able to send it with hourly precision.
|
|
"""
|
|
def execute(job_start) do
|
|
send_weekly_emails(job_start)
|
|
send_monthly_emails(job_start)
|
|
end
|
|
|
|
defp send_weekly_emails(job_start) do
|
|
sites = Repo.all(
|
|
from s in Plausible.Site,
|
|
join: wr in Plausible.Site.WeeklyReport, on: wr.site_id == s.id,
|
|
left_join: se in "sent_weekly_reports", on: se.site_id == s.id and se.year == fragment("EXTRACT(isoyear from (? at time zone ?))", ^job_start, s.timezone) and se.week == fragment("EXTRACT(week from (? at time zone ?))", ^job_start, s.timezone),
|
|
where: is_nil(se), # We haven't sent a report for this site on this week
|
|
where: fragment("EXTRACT(dow from (? at time zone ?))", ^job_start, s.timezone) == 1, # It's monday in the local timezone
|
|
where: fragment("EXTRACT(hour from (? at time zone ?))", ^job_start, s.timezone) >= 9, # It's after 9am
|
|
preload: [weekly_report: wr]
|
|
)
|
|
|
|
for site <- sites do
|
|
query = Stats.Query.from(site.timezone, %{"period" => "7d"})
|
|
|
|
for email <- site.weekly_report.recipients do
|
|
Logger.info("Sending weekly report for #{URI.encode_www_form(site.domain)} to #{email}")
|
|
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{URI.encode_www_form(site.domain)}/weekly-report/unsubscribe?email=#{email}"
|
|
send_report(email, site, "Weekly", unsubscribe_link, query)
|
|
end
|
|
|
|
weekly_report_sent(site, job_start)
|
|
end
|
|
end
|
|
|
|
defp send_monthly_emails(job_start) do
|
|
sites = Repo.all(
|
|
from s in Plausible.Site,
|
|
join: mr in Plausible.Site.MonthlyReport, on: mr.site_id == s.id,
|
|
left_join: se in "sent_monthly_reports", on: se.site_id == s.id and se.year == fragment("EXTRACT(year from (? at time zone ?))", ^job_start, s.timezone) and se.month == fragment("EXTRACT(month from (? at time zone ?))", ^job_start, s.timezone),
|
|
where: is_nil(se), # We haven't sent a report for this site this month
|
|
where: fragment("EXTRACT(day from (? at time zone ?))", ^job_start, s.timezone) == 1, # It's the 1st of the month in the local timezone
|
|
where: fragment("EXTRACT(hour from (? at time zone ?))", ^job_start, s.timezone) >= 9, # It's after 9am
|
|
preload: [monthly_report: mr]
|
|
)
|
|
|
|
for site <- sites do
|
|
last_month = job_start |> Timex.Timezone.convert(site.timezone) |> Timex.shift(months: -1) |> Timex.beginning_of_month
|
|
query = Stats.Query.from(site.timezone, %{"period" => "month", "date" => Timex.format!(last_month, "{ISOdate}")})
|
|
|
|
for email <- site.monthly_report.recipients do
|
|
Logger.info("Sending monthly report for #{site.domain} to #{email}")
|
|
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{URI.encode_www_form(site.domain)}/monthly-report/unsubscribe?email=#{email}"
|
|
send_report(email, site, Timex.format!(last_month, "{Mfull}"), unsubscribe_link, query)
|
|
end
|
|
|
|
monthly_report_sent(site, job_start)
|
|
end
|
|
end
|
|
|
|
defp send_report(email, site, name, unsubscribe_link, query) do
|
|
{pageviews, unique_visitors} = Stats.pageviews_and_visitors(site, query)
|
|
{change_pageviews, change_visitors} = Stats.compare_pageviews_and_visitors(site, query, {pageviews, unique_visitors})
|
|
bounce_rate = Stats.bounce_rate(site, query)
|
|
prev_bounce_rate = Stats.bounce_rate(site, Stats.Query.shift_back(query))
|
|
change_bounce_rate = if prev_bounce_rate > 0, do: bounce_rate - prev_bounce_rate
|
|
referrers = Stats.top_referrers(site, query)
|
|
pages = Stats.top_pages(site, query)
|
|
user = Plausible.Auth.find_user_by(email: email)
|
|
login_link = user && Plausible.Sites.is_owner?(user.id, site)
|
|
|
|
PlausibleWeb.Email.weekly_report(email, site,
|
|
unique_visitors: unique_visitors,
|
|
change_visitors: change_visitors,
|
|
pageviews: pageviews,
|
|
change_pageviews: change_pageviews,
|
|
bounce_rate: bounce_rate,
|
|
change_bounce_rate: change_bounce_rate,
|
|
referrers: referrers,
|
|
unsubscribe_link: unsubscribe_link,
|
|
login_link: login_link,
|
|
pages: pages,
|
|
query: query,
|
|
name: name
|
|
) |> Plausible.Mailer.deliver_now()
|
|
end
|
|
|
|
defp weekly_report_sent(site, time) do
|
|
{year, week} = time |> DateTime.to_date |> Timex.iso_week
|
|
|
|
Repo.insert_all("sent_weekly_reports", [%{
|
|
site_id: site.id,
|
|
year: year,
|
|
week: week,
|
|
timestamp: Timex.now()
|
|
}])
|
|
end
|
|
|
|
defp monthly_report_sent(site, time) do
|
|
date = DateTime.to_date(time)
|
|
|
|
Repo.insert_all("sent_monthly_reports", [%{
|
|
site_id: site.id,
|
|
year: date.year,
|
|
month: date.month,
|
|
timestamp: Timex.now()
|
|
}])
|
|
end
|
|
end
|