diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index 8794ea750..92345e536 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -495,11 +495,21 @@ defmodule PlausibleWeb.Api.StatsController do Stats.breakdown(site, query, metrics, pagination) |> transform_keys(%{channel: :name}) - json(conn, %{ - results: res, - meta: Stats.Breakdown.formatted_date_ranges(query), - skip_imported_reason: query.skip_imported_reason - }) + if params["csv"] do + if Filters.filtering_on_dimension?(query, "event:goal") do + res + |> transform_keys(%{visitors: :conversions}) + |> to_csv([:name, :conversions, :conversion_rate]) + else + res |> to_csv([:name, :visitors, :bounce_rate, :visit_duration]) + end + else + json(conn, %{ + results: res, + meta: Stats.Breakdown.formatted_date_ranges(query), + skip_imported_reason: query.skip_imported_reason + }) + end end on_ee do diff --git a/lib/plausible_web/controllers/stats_controller.ex b/lib/plausible_web/controllers/stats_controller.ex index 56968e7a9..df89b56cc 100644 --- a/lib/plausible_web/controllers/stats_controller.ex +++ b/lib/plausible_web/controllers/stats_controller.ex @@ -144,6 +144,15 @@ defmodule PlausibleWeb.StatsController do ~c"custom_props.csv" => fn -> Api.StatsController.all_custom_prop_values(conn, params) end } + # credo:disable-for-lines:7 + csvs = + if FunWithFlags.enabled?(:channels, for: site) || + FunWithFlags.enabled?(:channels, for: conn.assigns[:current_user]) do + Map.put(csvs, ~c"channels.csv", fn -> Api.StatsController.channels(conn, params) end) + else + csvs + end + csv_values = Map.values(csvs) |> Plausible.ClickhouseRepo.parallel_tasks() diff --git a/test/plausible_web/controllers/CSVs/30d-filter-goal/channels.csv b/test/plausible_web/controllers/CSVs/30d-filter-goal/channels.csv new file mode 100644 index 000000000..ef51cc387 --- /dev/null +++ b/test/plausible_web/controllers/CSVs/30d-filter-goal/channels.csv @@ -0,0 +1,2 @@ +name,conversions,conversion_rate +Direct,1,50.0 diff --git a/test/plausible_web/controllers/CSVs/30d-filter-path/channels.csv b/test/plausible_web/controllers/CSVs/30d-filter-path/channels.csv new file mode 100644 index 000000000..2a5bdece0 --- /dev/null +++ b/test/plausible_web/controllers/CSVs/30d-filter-path/channels.csv @@ -0,0 +1,2 @@ +name,visitors,bounce_rate,visit_duration +Organic Search,1,0,60 diff --git a/test/plausible_web/controllers/CSVs/30d/channels.csv b/test/plausible_web/controllers/CSVs/30d/channels.csv new file mode 100644 index 000000000..cb6427081 --- /dev/null +++ b/test/plausible_web/controllers/CSVs/30d/channels.csv @@ -0,0 +1,4 @@ +name,visitors,bounce_rate,visit_duration +Direct,2,50,30 +Organic Search,1,0,60 +Paid Search,1,100,0 diff --git a/test/plausible_web/controllers/CSVs/6m/channels.csv b/test/plausible_web/controllers/CSVs/6m/channels.csv new file mode 100644 index 000000000..115846994 --- /dev/null +++ b/test/plausible_web/controllers/CSVs/6m/channels.csv @@ -0,0 +1,4 @@ +name,visitors,bounce_rate,visit_duration +Direct,2,50,30 +Paid Search,2,100,0 +Organic Search,1,0,60 diff --git a/test/plausible_web/controllers/stats_controller_test.exs b/test/plausible_web/controllers/stats_controller_test.exs index a8831c8a7..7608cca93 100644 --- a/test/plausible_web/controllers/stats_controller_test.exs +++ b/test/plausible_web/controllers/stats_controller_test.exs @@ -208,6 +208,7 @@ defmodule PlausibleWeb.StatsControllerTest do assert ~c"pages.csv" in zip assert ~c"regions.csv" in zip assert ~c"sources.csv" in zip + assert ~c"channels.csv" in zip assert ~c"utm_campaigns.csv" in zip assert ~c"utm_contents.csv" in zip assert ~c"utm_mediums.csv" in zip @@ -423,6 +424,7 @@ defmodule PlausibleWeb.StatsControllerTest do expected_filenames = [ "visitors.csv", "sources.csv", + "channels.csv", "utm_mediums.csv", "utm_sources.csv", "utm_campaigns.csv", @@ -471,6 +473,13 @@ defmodule PlausibleWeb.StatsControllerTest do [""] ] + # Dummy - imported data is not actually included in exported CSVs yet + {~c"channels.csv", data} -> + assert parse_csv(data) == [ + ["name", "visitors", "bounce_rate", "visit_duration"], + [""] + ] + {~c"utm_mediums.csv", data} -> assert parse_csv(data) == [ ["name", "visitors", "bounce_rate", "visit_duration"], @@ -685,7 +694,8 @@ defmodule PlausibleWeb.StatsControllerTest do country_code: "EE", subdivision1_code: "EE-37", city_geoname_id: 588_409, - referrer_source: "Google" + referrer_source: "Google", + channel: "Organic Search" ), build(:pageview, user_id: 123, @@ -695,7 +705,8 @@ defmodule PlausibleWeb.StatsControllerTest do country_code: "EE", subdivision1_code: "EE-37", city_geoname_id: 588_409, - referrer_source: "Google" + referrer_source: "Google", + channel: "Organic Search" ), build(:pageview, pathname: "/", @@ -706,6 +717,7 @@ defmodule PlausibleWeb.StatsControllerTest do utm_source: "google", utm_content: "content", utm_term: "term", + channel: "Paid Search", browser: "Firefox", browser_version: "120", operating_system: "Mac", @@ -726,6 +738,7 @@ defmodule PlausibleWeb.StatsControllerTest do utm_campaign: "ads", country_code: "EE", referrer_source: "Google", + channel: "Paid Search", browser: "FirefoxNoVersion", operating_system: "MacNoVersion" ), diff --git a/test/test_helper.exs b/test/test_helper.exs index 963a84608..c2115df9c 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -6,6 +6,7 @@ end Mox.defmock(Plausible.HTTPClient.Mock, for: Plausible.HTTPClient.Interface) Application.ensure_all_started(:double) +FunWithFlags.enable(:channels) # Temporary flag to test `read_team_schemas` flag on all tests. if System.get_env("TEST_READ_TEAM_SCHEMAS") == "1" do FunWithFlags.enable(:read_team_schemas)