diff --git a/assets/js/dashboard/stats/conversions/index.js b/assets/js/dashboard/stats/conversions/index.js index f131bafd61fb..778a7c6da573 100644 --- a/assets/js/dashboard/stats/conversions/index.js +++ b/assets/js/dashboard/stats/conversions/index.js @@ -50,13 +50,14 @@ export default class Conversions extends React.Component { return (
-
+
{this.renderGoalText(goal.name)}
{numberFormatter(goal.count)} {numberFormatter(goal.total_count)} + {goal.conversion_rate}%
{ renderProps && } @@ -80,6 +81,7 @@ export default class Conversions extends React.Component {
Uniques Total + CR
diff --git a/assets/js/dashboard/stats/conversions/prop-breakdown.js b/assets/js/dashboard/stats/conversions/prop-breakdown.js index bbfc8d7a1546..5d1b73ba9ab1 100644 --- a/assets/js/dashboard/stats/conversions/prop-breakdown.js +++ b/assets/js/dashboard/stats/conversions/prop-breakdown.js @@ -41,7 +41,7 @@ export default class PropertyBreakdown extends React.Component { return (
-
+
{ value.name } @@ -50,6 +50,7 @@ export default class PropertyBreakdown extends React.Component {
{numberFormatter(value.count)} {numberFormatter(value.total_count)} + {numberFormatter(value.conversion_rate)}%
) diff --git a/lib/plausible/stats/query.ex b/lib/plausible/stats/query.ex index 957570768a5b..100b4eaff297 100644 --- a/lib/plausible/stats/query.ex +++ b/lib/plausible/stats/query.ex @@ -134,6 +134,8 @@ defmodule Plausible.Stats.Query do defp parse_filters(params) do if params["filters"] do Jason.decode!(params["filters"]) + else + %{} end end end diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index f19f1b91bd49..da9644228aa1 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -45,15 +45,8 @@ defmodule PlausibleWeb.Api.StatsController do completions = Stats.total_events(site, query) prev_completions = Stats.total_events(site, prev_query) - conversion_rate = - if unique_visitors > 0, - do: Float.round(converted_visitors / unique_visitors * 100, 1), - else: 0.0 - - prev_conversion_rate = - if prev_unique_visitors > 0, - do: Float.round(prev_converted_visitors / prev_unique_visitors * 100, 1), - else: 0.0 + conversion_rate = calculate_cr(unique_visitors, converted_visitors) + prev_conversion_rate = calculate_cr(prev_unique_visitors, prev_converted_visitors) [ %{ @@ -257,12 +250,24 @@ defmodule PlausibleWeb.Api.StatsController do json(conn, Stats.top_screen_sizes(site, query)) end + defp calculate_cr(unique_visitors, converted_visitors) do + if unique_visitors > 0, + do: Float.round(converted_visitors / unique_visitors * 100, 1), + else: 0.0 + end + def conversions(conn, params) do site = conn.assigns[:site] query = Query.from(site.timezone, params) + total_filter = Map.merge(query.filters, %{"goal" => nil, "props" => nil}) + unique_visitors = Stats.unique_visitors(site, %{query | filters: total_filter}) prop_names = Stats.all_props(site, query) conversions = Stats.goal_conversions(site, query) - |> Enum.map(fn goal -> Map.put(goal, :prop_names, prop_names[goal[:name]]) end) + |> Enum.map(fn goal -> + goal + |> Map.put(:prop_names, prop_names[goal[:name]]) + |> Map.put(:conversion_rate, calculate_cr(unique_visitors, goal[:count])) + end) json(conn, conversions) end @@ -270,8 +275,14 @@ defmodule PlausibleWeb.Api.StatsController do def prop_breakdown(conn, params) do site = conn.assigns[:site] query = Query.from(site.timezone, params) + total_filter = Map.merge(query.filters, %{"goal" => nil, "props" => nil}) + unique_visitors = Stats.unique_visitors(site, %{query | filters: total_filter}) + props = Stats.property_breakdown(site, query, params["prop_name"]) + |> Enum.map(fn prop -> + Map.put(prop, :conversion_rate, calculate_cr(unique_visitors, prop[:count])) + end) - json(conn, Stats.property_breakdown(site, query, params["prop_name"])) + json(conn, props) end def current_visitors(conn, _) do diff --git a/test/plausible_web/controllers/api/stats_controller/conversions_test.exs b/test/plausible_web/controllers/api/stats_controller/conversions_test.exs index 2d705d13ccd7..7a9eb1d71e78 100644 --- a/test/plausible_web/controllers/api/stats_controller/conversions_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/conversions_test.exs @@ -12,8 +12,8 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&date=2019-01-01") assert json_response(conn, 200) == [ - %{"name" => "Signup", "count" => 3, "total_count" => 3, "prop_names" => ["variant"]}, - %{"name" => "Visit /register", "count" => 2, "total_count" => 2, "prop_names" => nil} + %{"name" => "Signup", "count" => 3, "total_count" => 3, "prop_names" => ["variant"], "conversion_rate" => 50.0}, + %{"name" => "Visit /register", "count" => 2, "total_count" => 2, "prop_names" => nil, "conversion_rate" => 33.3} ] end end @@ -34,8 +34,8 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do ) assert json_response(conn, 200) == [ - %{"name" => "Signup", "count" => 3, "total_count" => 3, "prop_names" => ["variant"]} - ] + %{"name" => "Signup", "count" => 3, "total_count" => 3, "prop_names" => ["variant"], "conversion_rate" => 50.0} + ] end end @@ -54,8 +54,8 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do ) assert json_response(conn, 200) == [ - %{"count" => 2, "name" => "B", "total_count" => 2}, - %{"count" => 1, "name" => "A", "total_count" => 1} + %{"count" => 2, "name" => "B", "total_count" => 2, "conversion_rate" => 33.3}, + %{"count" => 1, "name" => "A", "total_count" => 1, "conversion_rate" => 16.7} ] end end