diff --git a/CHANGELOG.md b/CHANGELOG.md
index 355bde1c0e68..871f965cf0fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file.
- Improve site listing UX and design plausible/analytics#438
- Improve onboarding UX and design plausible/analytics#441
- Allows outbound link tracking script to use new tab redirection plausible/analytics#494
+- "This Month" view is now Month-to-date for the current month plausible/analytics#491
### Fixed
- Do not error when activating an already activated account plausible/analytics#370
diff --git a/assets/js/dashboard/date.js b/assets/js/dashboard/date.js
index 7faa8d0d0921..f3f462a34211 100644
--- a/assets/js/dashboard/date.js
+++ b/assets/js/dashboard/date.js
@@ -67,3 +67,7 @@ export function isSameMonth(date1, date2) {
export function isToday(site, date) {
return formatISO(date) === formatISO(nowForSite(site))
}
+
+export function isThisMonth(site, date) {
+ return formatMonthYYYY(date) === formatMonthYYYY(nowForSite(site))
+}
diff --git a/assets/js/dashboard/datepicker.js b/assets/js/dashboard/datepicker.js
index d4045257b4cd..5cf23dde8a87 100644
--- a/assets/js/dashboard/datepicker.js
+++ b/assets/js/dashboard/datepicker.js
@@ -2,7 +2,7 @@ import React from 'react';
import Transition from "../transition.js";
import { withRouter, Link } from 'react-router-dom'
import Flatpickr from "react-flatpickr";
-import {shiftDays, shiftMonths, formatDay, formatDayShort, formatMonthYYYY, formatISO, isToday, lastMonth, nowForSite, isSameMonth} from './date'
+import {shiftDays, shiftMonths, formatDay, formatDayShort, formatMonthYYYY, formatISO, isToday, lastMonth, nowForSite, isSameMonth, isThisMonth} from './date'
import { navigateToQuery, QueryLink } from './query.js'
@@ -87,7 +87,11 @@ class DatePicker extends React.Component {
} else if (query.period === '30d') {
return 'Last 30 days'
} else if (query.period === 'month') {
- return formatMonthYYYY(query.date)
+ if (isThisMonth(site, query.date)) {
+ return 'Month to Date'
+ } else {
+ return formatMonthYYYY(query.date)
+ }
} else if (query.period === '6mo') {
return 'Last 6 months'
} else if (query.period === '12mo') {
@@ -198,7 +202,7 @@ class DatePicker extends React.Component {
- { this.renderLink('month', 'This month') }
+ { this.renderLink('month', 'Month to Date') }
{ this.renderLink('month', 'Last month', {date: lastMonth(this.props.site)}) }
diff --git a/lib/plausible/stats/query.ex b/lib/plausible/stats/query.ex
index 100b4eaff297..8645a3d92c2b 100644
--- a/lib/plausible/stats/query.ex
+++ b/lib/plausible/stats/query.ex
@@ -6,7 +6,19 @@ defmodule Plausible.Stats.Query do
Map.put(query, :date_range, Date.range(new_date, new_date))
end
- def shift_back(query) do
+ def shift_back(%__MODULE__{period: "month"} = query, site) do
+ {new_first, new_last} = if Timex.compare(Timex.now(site.timezone), query.date_range.first, :month) == 0 do # Querying current month to date
+ diff = Timex.diff(Timex.beginning_of_month(Timex.now(site.timezone)), Timex.now(site.timezone), :days) - 1
+ {query.date_range.first |> Timex.shift(days: diff), Timex.now(site.timezone) |> Timex.shift(days: diff)}
+ else
+ diff = Timex.diff(query.date_range.first, query.date_range.last, :days) - 1
+ {query.date_range.first |> Timex.shift(days: diff), query.date_range.last |> Timex.shift(days: diff)}
+ end
+
+ Map.put(query, :date_range, Date.range(new_first, new_last))
+ end
+
+ def shift_back(query, _site) do
diff = Timex.diff(query.date_range.first, query.date_range.last, :days) - 1
new_first = query.date_range.first |> Timex.shift(days: diff)
new_last = query.date_range.last |> Timex.shift(days: diff)
diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex
index e9c165bc243e..7e2ae5073aa5 100644
--- a/lib/plausible_web/controllers/api/stats_controller.ex
+++ b/lib/plausible_web/controllers/api/stats_controller.ex
@@ -77,13 +77,14 @@ defmodule PlausibleWeb.Api.StatsController do
end
defp fetch_top_stats(site, query) do
- prev_query = Query.shift_back(query)
+ prev_query = Query.shift_back(query, site)
{pageviews, visitors} = Stats.pageviews_and_visitors(site, query)
{prev_pageviews, prev_visitors} = Stats.pageviews_and_visitors(site, prev_query)
bounce_rate = Stats.bounce_rate(site, query)
prev_bounce_rate = Stats.bounce_rate(site, prev_query)
change_bounce_rate = if prev_bounce_rate > 0, do: bounce_rate - prev_bounce_rate
+
visit_duration =
if !query.filters["page"] do
duration = Stats.visit_duration(site, query)