mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 09:33:19 +03:00
Fix exit pages when using a goal filter
This commit is contained in:
parent
03e46d2ed5
commit
49214eaff8
@ -7,7 +7,7 @@ defmodule Plausible.Stats.Base do
|
||||
def base_event_query(site, query) do
|
||||
events_q = query_events(site, query)
|
||||
|
||||
if Enum.any?(Filters.visit_props(), &query.filters["visit:" <> &1]) do
|
||||
if Enum.any?(Filters.visit_props() ++ ["goal"], &query.filters["visit:" <> &1]) do
|
||||
sessions_q =
|
||||
from(
|
||||
s in query_sessions(site, query),
|
||||
@ -67,7 +67,7 @@ defmodule Plausible.Stats.Base do
|
||||
end
|
||||
|
||||
q =
|
||||
case query.filters["visit:goal"] do
|
||||
case query.filters["event:goal"] do
|
||||
{:is, :page, path} ->
|
||||
from(e in q, where: e.pathname == ^path)
|
||||
|
||||
@ -127,6 +127,30 @@ defmodule Plausible.Stats.Base do
|
||||
where: s.timestamp >= ^first_datetime and s.start < ^last_datetime
|
||||
)
|
||||
|
||||
sessions_q =
|
||||
case query.filters["visit:goal"] do
|
||||
nil ->
|
||||
sessions_q
|
||||
|
||||
goal_filter ->
|
||||
events_query =
|
||||
Query.put_filter(query, "event:goal", goal_filter)
|
||||
|> Query.put_filter("event:name", nil)
|
||||
|> Query.put_filter("event:page", nil)
|
||||
|
||||
events_q =
|
||||
from(
|
||||
s in query_events(site, events_query),
|
||||
select: %{session_id: fragment("DISTINCT ?", s.session_id)}
|
||||
)
|
||||
|
||||
from(
|
||||
s in sessions_q,
|
||||
join: sq in subquery(events_q),
|
||||
on: s.session_id == sq.session_id
|
||||
)
|
||||
end
|
||||
|
||||
Enum.reduce(Filters.visit_props(), sessions_q, fn prop_name, sessions_q ->
|
||||
filter = query.filters["visit:" <> prop_name]
|
||||
prop_name = Map.get(@api_prop_name_to_db, prop_name, prop_name)
|
||||
@ -216,7 +240,7 @@ defmodule Plausible.Stats.Base do
|
||||
def select_session_metrics(q, ["visits" | rest]) do
|
||||
from(s in q,
|
||||
select_merge: %{
|
||||
"visits" => fragment("toUInt64(round(sum(?) * any(_sample_factor)))", s.sign)
|
||||
"visits" => fragment("toUInt64(round(uniq(?) * any(_sample_factor)))", s.session_id)
|
||||
}
|
||||
)
|
||||
|> select_session_metrics(rest)
|
||||
|
@ -8,7 +8,7 @@ defmodule Plausible.Stats.Breakdown do
|
||||
@session_metrics ["visits", "bounce_rate", "visit_duration"]
|
||||
@event_props ["event:page", "event:page_match", "event:name"]
|
||||
|
||||
def breakdown(site, query, "visit:goal", metrics, pagination) do
|
||||
def breakdown(site, query, "event:goal", metrics, pagination) do
|
||||
{event_goals, pageview_goals} =
|
||||
Plausible.Repo.all(from g in Plausible.Goal, where: g.domain == ^site.domain)
|
||||
|> Enum.split_with(fn goal -> goal.event_name end)
|
||||
@ -47,7 +47,7 @@ defmodule Plausible.Stats.Breakdown do
|
||||
|> ClickhouseRepo.all()
|
||||
|> Enum.map(fn row -> Map.delete(row, "index") end)
|
||||
|
||||
zip_results(event_goals, page_goals, "visit:goal", metrics)
|
||||
zip_results(event_goals, page_goals, "event:goal", metrics)
|
||||
end
|
||||
|
||||
def breakdown(site, query, "event:props:" <> custom_prop, metrics, pagination) do
|
||||
@ -174,7 +174,7 @@ defmodule Plausible.Stats.Breakdown do
|
||||
end
|
||||
|
||||
defp filter_converted_sessions(db_query, site, query) do
|
||||
if query.filters["event:name"] || query.filters["event:page"] || query.filters["visit:goal"] do
|
||||
if query.filters["event:name"] || query.filters["event:page"] || query.filters["event:goal"] do
|
||||
converted_sessions =
|
||||
from(e in query_events(site, query),
|
||||
select: %{session_id: fragment("DISTINCT ?", e.session_id)}
|
||||
|
@ -45,7 +45,7 @@ defmodule Plausible.Stats.Filters do
|
||||
{:is, :event, event}
|
||||
end
|
||||
|
||||
Map.put(new_filters, "visit:goal", filter)
|
||||
Map.put(new_filters, "event:goal", filter)
|
||||
|
||||
name in (@visit_props ++ ["goal"]) ->
|
||||
Map.put(new_filters, "visit:" <> name, filter_value(name, val))
|
||||
|
@ -216,7 +216,7 @@ defmodule Plausible.Stats.Query do
|
||||
|
||||
cond do
|
||||
is_list && is_glob -> raise "Not implemented"
|
||||
key == "visit:goal" -> {key, parse_goal_filter(val)}
|
||||
key == "event:goal" -> {key, parse_goal_filter(val)}
|
||||
is_list -> {key, {:member, String.split(val, "|")}}
|
||||
is_glob -> {key, {:matches, val}}
|
||||
is_negated -> {key, {:is_not, val}}
|
||||
|
@ -10,7 +10,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
query = Query.from(site.timezone, params) |> Filters.add_prefix()
|
||||
|
||||
query =
|
||||
case query.filters["visit:goal"] do
|
||||
case query.filters["event:goal"] do
|
||||
nil -> Query.put_filter(query, "event:name", {:is, "pageview"})
|
||||
_ -> query
|
||||
end
|
||||
@ -86,8 +86,8 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
{stats, nil}
|
||||
end
|
||||
|
||||
defp fetch_top_stats(site, %Query{filters: %{"visit:goal" => _goal}} = query) do
|
||||
total_filter = Map.merge(query.filters, %{"visit:goal" => nil})
|
||||
defp fetch_top_stats(site, %Query{filters: %{"event:goal" => _goal}} = query) do
|
||||
total_filter = Map.merge(query.filters, %{"event:goal" => nil})
|
||||
prev_query = Query.shift_back(query, site)
|
||||
|
||||
%{
|
||||
@ -320,7 +320,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
query = Query.from(site.timezone, params) |> Filters.add_prefix()
|
||||
|
||||
query =
|
||||
case query.filters["visit:goal"] do
|
||||
case query.filters["event:goal"] do
|
||||
nil -> Query.put_filter(query, "event:name", {:is, "pageview"})
|
||||
_ -> query
|
||||
end
|
||||
@ -362,8 +362,13 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
Stats.breakdown(site, query, "visit:exit_page", metrics, {limit, page})
|
||||
|> transform_keys(%{"exit_page" => "name", "visits" => "exits", "visitors" => "count"})
|
||||
|
||||
page_filter_expr = Enum.map(exit_pages, & &1["page"]) |> Enum.join("|")
|
||||
total_visits_query = Query.put_filter(query, "page", page_filter_expr)
|
||||
pages = Enum.map(exit_pages, & &1["name"])
|
||||
|
||||
total_visits_query =
|
||||
Query.put_filter(query, "event:page", {:member, pages})
|
||||
|> Query.put_filter("event:goal", nil)
|
||||
|> Query.put_filter("event:name", {:is, "pageview"})
|
||||
|> Query.put_filter("visit:goal", query.filters["event:goal"])
|
||||
|
||||
total_pageviews =
|
||||
Stats.breakdown(site, total_visits_query, "event:page", ["pageviews"], {limit, 1})
|
||||
@ -373,7 +378,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
exit_rate =
|
||||
case Enum.find(total_pageviews, &(&1["page"] == exit_page["name"])) do
|
||||
%{"pageviews" => pageviews} ->
|
||||
round(exit_page["exits"] / pageviews * 100)
|
||||
Float.floor(exit_page["exits"] / pageviews * 100)
|
||||
|
||||
nil ->
|
||||
nil
|
||||
@ -477,7 +482,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
query = Query.from(site.timezone, params) |> Filters.add_prefix()
|
||||
pagination = parse_pagination(params)
|
||||
|
||||
total_filter = Map.merge(query.filters, %{"visit:goal" => nil})
|
||||
total_filter = Map.merge(query.filters, %{"event:goal" => nil})
|
||||
|
||||
%{"visitors" => %{"value" => total_visitors}} =
|
||||
Stats.aggregate(site, %{query | filters: total_filter}, ["visitors"])
|
||||
@ -485,7 +490,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
prop_names = Stats.props(site, query)
|
||||
|
||||
conversions =
|
||||
Stats.breakdown(site, query, "visit:goal", ["visitors", "events"], pagination)
|
||||
Stats.breakdown(site, query, "event:goal", ["visitors", "events"], pagination)
|
||||
|> transform_keys(%{"goal" => "name", "visitors" => "count", "events" => "total_count"})
|
||||
|> Enum.map(fn goal ->
|
||||
goal
|
||||
@ -501,7 +506,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
query = Query.from(site.timezone, params) |> Filters.add_prefix()
|
||||
pagination = parse_pagination(params)
|
||||
|
||||
total_filter = Map.merge(query.filters, %{"visit:goal" => nil})
|
||||
total_filter = Map.merge(query.filters, %{"event:goal" => nil})
|
||||
|
||||
%{"visitors" => %{"value" => unique_visitors}} =
|
||||
Stats.aggregate(site, %{query | filters: total_filter}, ["visitors"])
|
||||
|
@ -841,7 +841,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
}
|
||||
end
|
||||
|
||||
test "visit:goal pageview filter for breakdown by visit source", %{conn: conn, site: site} do
|
||||
test "event:goal pageview filter for breakdown by visit source", %{conn: conn, site: site} do
|
||||
populate_stats(site, [
|
||||
build(:pageview,
|
||||
referrer_source: "Bing",
|
||||
@ -865,7 +865,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
"period" => "day",
|
||||
"date" => "2021-01-01",
|
||||
"property" => "visit:source",
|
||||
"filters" => "visit:goal == Visit /plausible.io"
|
||||
"filters" => "event:goal == Visit /plausible.io"
|
||||
})
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
@ -875,7 +875,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
}
|
||||
end
|
||||
|
||||
test "visit:goal custom event filter for breakdown by visit source", %{conn: conn, site: site} do
|
||||
test "event:goal custom event filter for breakdown by visit source", %{conn: conn, site: site} do
|
||||
populate_stats(site, [
|
||||
build(:pageview,
|
||||
referrer_source: "Bing",
|
||||
@ -899,7 +899,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
"period" => "day",
|
||||
"date" => "2021-01-01",
|
||||
"property" => "visit:source",
|
||||
"filters" => "visit:goal == Register"
|
||||
"filters" => "event:goal == Register"
|
||||
})
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
@ -909,7 +909,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
}
|
||||
end
|
||||
|
||||
test "visit:goal custom event filter for breakdown by event page", %{conn: conn, site: site} do
|
||||
test "event:goal custom event filter for breakdown by event page", %{conn: conn, site: site} do
|
||||
populate_stats(site, [
|
||||
build(:event,
|
||||
pathname: "/en/register",
|
||||
@ -930,7 +930,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
"site_id" => site.domain,
|
||||
"period" => "day",
|
||||
"property" => "event:page",
|
||||
"filters" => "visit:goal == Register"
|
||||
"filters" => "event:goal == Register"
|
||||
})
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
|
@ -163,7 +163,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
|
||||
conn = get(conn, "/api/stats/#{site.domain}/exit-pages?period=day&date=2021-01-01")
|
||||
|
||||
assert json_response(conn, 200) == [
|
||||
%{"name" => "/page1", "count" => 2, "exits" => 2, "exit_rate" => 67},
|
||||
%{"name" => "/page1", "count" => 2, "exits" => 2, "exit_rate" => 66},
|
||||
%{"name" => "/page2", "count" => 1, "exits" => 1, "exit_rate" => 100}
|
||||
]
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user