Query imported data for views_per_visit (#3830)

* query imported data for views_per_visit

* changelog update
This commit is contained in:
RobertJoonas 2024-02-26 15:54:49 +00:00 committed by GitHub
parent cc867396b2
commit dd428430f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 30 additions and 14 deletions

View File

@ -2,6 +2,7 @@
All notable changes to this project will be documented in this file.
### Added
- Query the `views_per_visit` metric based on imported data as well if possible
- Group `operating_system_versions` by `operating_system` in Stats API breakdown
- Add `operating_system_versions.csv` into the CSV export
- Display `Total visitors`, `Conversions`, and `CR` in the "Details" views of Countries, Regions and Cities (when filtering by a goal)

View File

@ -69,9 +69,6 @@ export default class TopStats extends React.Component {
let statName = stat.name.toLowerCase()
statName = stat.value === 1 ? statName.slice(0, -1) : statName
const { topStatData, lastLoadTimestamp } = this.props
const showingImported = topStatData?.imported_source && topStatData?.with_imported
return (
<div>
{query.comparison && <div className="whitespace-nowrap">
@ -83,8 +80,7 @@ export default class TopStats extends React.Component {
{this.topStatNumberLong(stat.name, stat.value)} {statName}
</div>}
{stat.name === 'Current visitors' && <p className="font-normal text-xs">Last updated <SecondsSinceLastLoad lastLoadTimestamp={lastLoadTimestamp}/>s ago</p>}
{stat.name === 'Views per visit' && showingImported && <p className="font-normal text-xs whitespace-nowrap">Based only on native data</p>}
{stat.name === 'Current visitors' && <p className="font-normal text-xs">Last updated <SecondsSinceLastLoad lastLoadTimestamp={this.props.lastLoadTimestamp}/>s ago</p>}
</div>
)
}

View File

@ -336,7 +336,8 @@ defmodule Plausible.Stats.Base do
from(s in q,
select_merge: %{
views_per_visit:
fragment("ifNotFinite(round(sum(? * ?) / sum(?), 2), 0)", s.sign, s.pageviews, s.sign)
fragment("ifNotFinite(round(sum(? * ?) / sum(?), 2), 0)", s.sign, s.pageviews, s.sign),
__internal_visits: fragment("toUInt32(sum(sign))")
}
)
|> select_session_metrics(rest, query)

View File

@ -424,6 +424,16 @@ defmodule Plausible.Stats.Imported do
|> select_imported_metrics(rest)
end
defp select_imported_metrics(q, [:views_per_visit | rest]) do
q
|> where([i], i.pageviews > 0)
|> select_merge([i], %{
pageviews: sum(i.pageviews),
__internal_visits: sum(i.visits)
})
|> select_imported_metrics(rest)
end
defp select_imported_metrics(q, [_ | rest]) do
q
|> select_imported_metrics(rest)
@ -462,8 +472,16 @@ defmodule Plausible.Stats.Imported do
defp select_joined_metrics(q, [:views_per_visit | rest]) do
q
|> select_merge([s, _i], %{
views_per_visit: s.views_per_visit
|> select_merge([s, i], %{
views_per_visit:
fragment(
"round((? + ? * coalesce(?, 0)) / (coalesce(?, 0) + coalesce(?, 0)), 2)",
i.pageviews,
s.views_per_visit,
s.__internal_visits,
i.__internal_visits,
s.__internal_visits
)
})
|> select_joined_metrics(rest)
end

View File

@ -9,8 +9,8 @@ defmodule Plausible.Stats.Util do
Sometimes we need to manually add metrics in order to calculate the value for
other metrics. E.g:
* `__internal_visits` is fetched when querying bounce rate and visit duration,
as it is needed to calculate these from imported data.
* `__internal_visits` is fetched when querying bounce rate, visit duration,
or views_per_visit, as it is needed to calculate these from imported data.
* `visitors` metric might be added manually via `maybe_add_visitors_metric/1`,
in order to be able to calculate conversion rate.

View File

@ -1211,7 +1211,7 @@ defmodule Plausible.ImportedTest do
%{"name" => "Unique visitors", "value" => 1},
%{"name" => "Total visits", "value" => 1},
%{"name" => "Total pageviews", "value" => 1},
%{"name" => "Views per visit", "value" => +0.0},
%{"name" => "Views per visit", "value" => 1.0},
%{"name" => "Bounce rate", "value" => 0},
%{"name" => "Visit duration", "value" => 60}
]

View File

@ -420,7 +420,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
"visits" => %{"value" => 5, "change" => 150},
"pageviews" => %{"value" => 9, "change" => -10},
"bounce_rate" => %{"value" => 40, "change" => -10},
"views_per_visit" => %{"value" => 1.0, "change" => 100},
"views_per_visit" => %{"value" => 1.8, "change" => -64},
"visit_duration" => %{"value" => 20, "change" => -80}
}
end

View File

@ -387,7 +387,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
describe "GET /api/stats/top-stats - with imported data" do
setup [:create_user, :log_in, :create_new_site, :add_imported_data]
test "merges imported data into all top stat metrics except views_per_visit", %{
test "merges imported data into all top stat metrics", %{
conn: conn,
site: site
} do
@ -418,7 +418,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
%{"name" => "Unique visitors", "value" => 3},
%{"name" => "Total visits", "value" => 3},
%{"name" => "Total pageviews", "value" => 4},
%{"name" => "Views per visit", "value" => 1.5},
%{"name" => "Views per visit", "value" => 1.33},
%{"name" => "Bounce rate", "value" => 33},
%{"name" => "Visit duration", "value" => 303}
]