Fix custom property total conversions value not displayed & Export custom properties (#1456)

* Fix custom property total conversions value not displayed

The custom property conversion metrics are not consistent with the other
metrics resulting in the total conversions not being displayed in the
dashboard. This fixes that.

* Export custom props of current goal when filtering dashboard for goal

This makes the CSV export also output a `prop_breakdown.csv` file which,
for the currently filtered goal, contains the conversion data for each
of its configured properties.

* Add test for goal-filtered CSV export
This commit is contained in:
Matt Colligan 2021-11-10 14:53:38 +00:00 committed by GitHub
parent 7a02aae2a5
commit 3380685d40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 128 additions and 18 deletions

View File

@ -115,7 +115,8 @@ export default class PropertyBreakdown extends React.Component {
return (
<div className="flex items-center justify-between my-2" key={value.name}>
<Bar
count={value.visitors}
count={value.unique_conversions}
plot="unique_conversions"
all={this.state.breakdown}
bg="bg-red-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction={this.getBarMaxWidth()}
@ -123,13 +124,13 @@ export default class PropertyBreakdown extends React.Component {
{this.renderPropContent(value, query)}
</Bar>
<div className="dark:text-gray-200">
<span className="font-medium inline-block w-20 text-right">{numberFormatter(value.visitors)}</span>
<span className="font-medium inline-block w-20 text-right">{numberFormatter(value.unique_conversions)}</span>
{
viewport > MOBILE_UPPER_WIDTH ?
(
<span
className="font-medium inline-block w-20 text-right"
>{numberFormatter(value.total_count)}
>{numberFormatter(value.total_conversions)}
</span>
)
: null

View File

@ -611,13 +611,49 @@ defmodule PlausibleWeb.Api.StatsController do
Stats.breakdown(site, query, prop_name, ["visitors", "events"], pagination)
|> transform_keys(%{
params["prop_name"] => "name",
"events" => "total_conversions"
"events" => "total_conversions",
"visitors" => "unique_conversions"
})
|> Enum.map(fn prop ->
Map.put(prop, "conversion_rate", calculate_cr(unique_visitors, prop["visitors"]))
Map.put(
prop,
"conversion_rate",
calculate_cr(unique_visitors, prop["unique_conversions"])
)
end)
json(conn, props)
if params["csv"] do
props
else
json(conn, props)
end
end
def all_props_breakdown(conn, params) do
site = conn.assigns[:site]
query = Query.from(site.timezone, params) |> Filters.add_prefix()
headers = ["prop", "name", "unique_conversions", "total_conversions"]
prop_names =
if query.filters["event:goal"] do
{_, _, goal} = query.filters["event:goal"]
Stats.props(site, query)
|> Map.get(goal, [])
else
[]
end
values =
prop_names
|> Enum.map(fn prop ->
prop_breakdown(conn, Map.put(params, "prop_name", prop))
|> Enum.map(&Map.put(&1, "prop", prop))
end)
|> Enum.concat()
to_csv(values, headers)
end
def current_visitors(conn, _) do

View File

@ -71,7 +71,8 @@ defmodule PlausibleWeb.StatsController do
{'browsers.csv', fn -> Api.StatsController.browsers(conn, params) end},
{'operating_systems.csv', fn -> Api.StatsController.operating_systems(conn, params) end},
{'devices.csv', fn -> Api.StatsController.screen_sizes(conn, params) end},
{'conversions.csv', fn -> Api.StatsController.conversions(conn, params) end}
{'conversions.csv', fn -> Api.StatsController.conversions(conn, params) end},
{'prop_breakdown.csv', fn -> Api.StatsController.all_props_breakdown(conn, params) end}
]
csvs =

View File

@ -1,2 +1,2 @@
name,unique_conversions,total_conversions
Visit /some-other-page,1,1
Signup,1,1
1 name unique_conversions total_conversions
2 Visit /some-other-page Signup 1 1

View File

@ -0,0 +1 @@
name,visitors
1 name visitors

View File

@ -0,0 +1,2 @@
name,unique_entrances,total_entrances,visit_duration
/,1,1,0
1 name unique_entrances total_entrances visit_duration
2 / 1 1 0

View File

@ -0,0 +1,2 @@
name,unique_exits,total_exits,exit_rate
/,1,1,
1 name unique_exits total_exits exit_rate
2 / 1 1

View File

@ -0,0 +1,2 @@
name,visitors,bounce_rate,time_on_page
/,1,100,
1 name visitors bounce_rate time_on_page
2 / 1 100

View File

@ -0,0 +1,2 @@
prop,name,unique_conversions,total_conversions
variant,A,1,1
1 prop name unique_conversions total_conversions
2 variant A 1 1

View File

@ -0,0 +1,32 @@
date,visitors,pageviews,bounce_rate,visit_duration
2021-09-20,0,0,100,0
2021-09-21,0,0,,
2021-09-22,0,0,,
2021-09-23,0,0,,
2021-09-24,0,0,,
2021-09-25,0,0,,
2021-09-26,0,0,,
2021-09-27,0,0,,
2021-09-28,0,0,,
2021-09-29,0,0,,
2021-09-30,0,0,,
2021-10-01,0,0,,
2021-10-02,0,0,,
2021-10-03,0,0,,
2021-10-04,0,0,,
2021-10-05,0,0,,
2021-10-06,0,0,,
2021-10-07,0,0,,
2021-10-08,0,0,,
2021-10-09,0,0,,
2021-10-10,0,0,,
2021-10-11,0,0,,
2021-10-12,0,0,,
2021-10-13,0,0,,
2021-10-14,0,0,,
2021-10-15,0,0,,
2021-10-16,0,0,,
2021-10-17,0,0,,
2021-10-18,0,0,,
2021-10-19,1,0,100,0
2021-10-20,0,0,0,60
1 date visitors pageviews bounce_rate visit_duration
2 2021-09-20 0 0 100 0
3 2021-09-21 0 0
4 2021-09-22 0 0
5 2021-09-23 0 0
6 2021-09-24 0 0
7 2021-09-25 0 0
8 2021-09-26 0 0
9 2021-09-27 0 0
10 2021-09-28 0 0
11 2021-09-29 0 0
12 2021-09-30 0 0
13 2021-10-01 0 0
14 2021-10-02 0 0
15 2021-10-03 0 0
16 2021-10-04 0 0
17 2021-10-05 0 0
18 2021-10-06 0 0
19 2021-10-07 0 0
20 2021-10-08 0 0
21 2021-10-09 0 0
22 2021-10-10 0 0
23 2021-10-11 0 0
24 2021-10-12 0 0
25 2021-10-13 0 0
26 2021-10-14 0 0
27 2021-10-15 0 0
28 2021-10-16 0 0
29 2021-10-17 0 0
30 2021-10-18 0 0
31 2021-10-19 1 0 100 0
32 2021-10-20 0 0 0 60

View File

@ -0,0 +1,2 @@
name,visitors
,1
1 name visitors
2 1

View File

@ -0,0 +1 @@
name,unique_conversions,total_conversions
1 name unique_conversions total_conversions

View File

@ -0,0 +1,2 @@
name,visitors
,1
1 name visitors
2 1

View File

@ -0,0 +1,2 @@
name,visitors
,1
1 name visitors
2 1

View File

@ -0,0 +1 @@
prop,name,unique_conversions,total_conversions
1 prop name unique_conversions total_conversions

View File

@ -0,0 +1 @@
name,visitors,bounce_rate,visit_duration
1 name visitors bounce_rate visit_duration

View File

@ -0,0 +1 @@
name,visitors,bounce_rate,visit_duration
1 name visitors bounce_rate visit_duration

View File

@ -0,0 +1 @@
name,visitors,bounce_rate,visit_duration
1 name visitors bounce_rate visit_duration

View File

@ -0,0 +1 @@
name,visitors,bounce_rate,visit_duration
1 name visitors bounce_rate visit_duration

View File

@ -1,2 +1,2 @@
name,unique_conversions,total_conversions
Visit /some-other-page,1,1
Signup,1,1

1 name unique_conversions total_conversions
2 Visit /some-other-page Signup 1 1

View File

@ -0,0 +1 @@
prop,name,unique_conversions,total_conversions
1 prop name unique_conversions total_conversions

View File

@ -1,2 +1,2 @@
name,unique_conversions,total_conversions
Visit /some-other-page,1,1
Signup,1,1

1 name unique_conversions total_conversions
2 Visit /some-other-page Signup 1 1

View File

@ -0,0 +1 @@
prop,name,unique_conversions,total_conversions
1 prop name unique_conversions total_conversions

View File

@ -4,4 +4,4 @@ date,visitors,pageviews,bounce_rate,visit_duration
2021-07-01,0,0,,
2021-08-01,0,0,,
2021-09-01,1,1,100,0
2021-10-01,2,3,50,30
2021-10-01,2,3,67,20

1 date visitors pageviews bounce_rate visit_duration
4 2021-07-01 0 0
5 2021-08-01 0 0
6 2021-09-01 1 1 100 0
7 2021-10-01 2 3 50 67 30 20

View File

@ -112,13 +112,13 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
assert json_response(conn, 200) == [
%{
"visitors" => 2,
"unique_conversions" => 2,
"name" => "B",
"total_conversions" => 2,
"conversion_rate" => 66.7
},
%{
"visitors" => 1,
"unique_conversions" => 1,
"name" => "A",
"total_conversions" => 1,
"conversion_rate" => 33.3
@ -148,13 +148,13 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
assert json_response(conn, 200) == [
%{
"visitors" => 2,
"unique_conversions" => 2,
"name" => "(none)",
"total_conversions" => 2,
"conversion_rate" => 66.7
},
%{
"visitors" => 1,
"unique_conversions" => 1,
"name" => "A",
"total_conversions" => 1,
"conversion_rate" => 33.3
@ -182,7 +182,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
assert json_response(conn, 200) == [
%{
"visitors" => 1,
"unique_conversions" => 1,
"name" => "B",
"total_conversions" => 1,
"conversion_rate" => 50.0

View File

@ -83,7 +83,7 @@ defmodule PlausibleWeb.StatsControllerTest do
filters = Jason.encode!(%{page: "/some-other-page"})
conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}")
assert_zip(conn, "30d-filtered")
assert_zip(conn, "30d-filter-path")
end
end
@ -140,10 +140,27 @@ defmodule PlausibleWeb.StatsControllerTest do
country_code: "EE",
referrer_source: "Google",
browser: "ABrowserName"
),
build(:event,
timestamp: Timex.shift(~N[2021-10-20 12:00:00], days: -1),
name: "Signup",
"meta.key": ["variant"],
"meta.value": ["A"]
)
])
insert(:goal, %{domain: site.domain, page_path: "/some-other-page"})
insert(:goal, %{domain: site.domain, event_name: "Signup"})
end
describe "GET /:website/export - with goal filter" do
setup [:create_user, :create_new_site, :log_in]
test "exports goal-filtered data in zipped csvs", %{conn: conn, site: site} do
populate_exported_stats(site)
filters = Jason.encode!(%{goal: "Signup"})
conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}")
assert_zip(conn, "30d-filter-goal")
end
end
describe "GET /share/:slug" do