Leon4gr45's picture
Upload folder using huggingface_hub (part 6)
6778ee0 verified
Raw
History Blame Contribute Delete
84 kB
defmodule PlausibleWeb.Api.StatsController.SourcesTest do
use PlausibleWeb.ConnCase
@user_id Enum.random(1000..9999)
defp query_sources(conn, site, opts) do
params = %{
"dimensions" => Keyword.get(opts, :dimensions, ["visit:source"]),
"date_range" => Keyword.get(opts, :date_range, "all"),
"relative_date" => Keyword.get(opts, :relative_date, nil),
"filters" => Keyword.get(opts, :filters, []),
"metrics" => Keyword.get(opts, :metrics, ["visitors", "percentage"]),
"include" => Keyword.get(opts, :include, nil),
"pagination" => Keyword.get(opts, :pagination, nil),
"order_by" => Keyword.get(opts, :order_by, nil)
}
conn
|> post("/api/stats/#{site.domain}/query", params)
|> json_response(200)
end
describe "GET /api/stats/:domain/sources" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top sources by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
),
build(:pageview)
])
response = query_sources(conn, site, date_range: "day")
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [3, 50.0]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [2, 33.33]},
%{"dimensions" => ["Direct / None"], "metrics" => [1, 16.67]}
]
end
test "returns top sources with :is filter on custom pageview props", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
"meta.key": ["author"],
"meta.value": ["John Doe"],
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["John Doe"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["John Doe"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
referrer: "facebook.com",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
filters: [["is", "event:props:author", ["John Doe"]]]
)
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
assert response["query"]["date_range"] == [
"2021-01-01T00:00:00Z",
"2021-01-01T23:59:59Z"
]
end
test "returns top sources with :is_not filter on custom pageview props", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
"meta.key": ["author"],
"meta.value": ["John Doe"],
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
"meta.key": ["author"],
"meta.value": ["other"],
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["other"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
referrer: "facebook.com",
"meta.key": ["author"],
"meta.value": ["John Doe"],
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
filters: [["is_not", "event:props:author", ["John Doe"]]]
)
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
end
test "returns top sources with :is (none) filter on custom pageview props", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
"meta.key": ["author"],
"meta.value": ["John Doe"],
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["other"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
referrer: "facebook.com",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
referrer: "facebook.com",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
filters: [["is", "event:props:author", ["(none)"]]]
)
assert response["results"] == [
%{"dimensions" => ["Facebook"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
end
test "returns top sources with :is_not (none) filter on custom pageview props", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
"meta.key": ["logged_in"],
"meta.value": ["true"],
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
"meta.key": ["author"],
"meta.value": ["other"],
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["other"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["author"],
"meta.value": ["another"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
referrer: "facebook.com",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
filters: [["is_not", "event:props:author", ["(none)"]]]
)
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
end
test "returns top sources with imported data", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, referrer_source: "Google", referrer: "google.com"),
build(:pageview, referrer_source: "Google", referrer: "google.com"),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
)
])
populate_stats(site, [
build(:imported_visitors),
build(:imported_visitors),
build(:imported_visitors),
build(:imported_sources,
source: "Google",
visitors: 2
),
build(:imported_sources,
source: "DuckDuckGo",
visitors: 1
)
])
response1 = query_sources(conn, site, date_range: "day")
assert response1["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
response2 = query_sources(conn, site, date_range: "day", include: %{"imports" => true})
assert response2["results"] == [
%{"dimensions" => ["Google"], "metrics" => [4, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [2, 33.33]}
]
end
test "calculates bounce rate and visit duration for sources", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
order_by: [["visit_duration", "asc"]]
)
assert response["results"] == [
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 100, 0, 50.0]},
%{"dimensions" => ["Google"], "metrics" => [1, 0, 900, 50.0]}
]
end
test "calculates bounce rate and visit duration for sources with imported data", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors, date: ~D[2021-01-01]),
build(:imported_visitors, date: ~D[2021-01-01]),
build(:imported_visitors, date: ~D[2021-01-01]),
build(:imported_sources,
source: "Google",
date: ~D[2021-01-01],
visitors: 2,
visits: 3,
bounces: 1,
visit_duration: 900
),
build(:imported_sources,
source: "DuckDuckGo",
date: ~D[2021-01-01],
visitors: 1,
visits: 1,
visit_duration: 100,
bounces: 0
)
])
response1 =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
order_by: [["visit_duration", "asc"]]
)
assert response1["results"] == [
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 100, 0, 50.0]},
%{"dimensions" => ["Google"], "metrics" => [1, 0, 900, 50.0]}
]
response2 =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["Google"], "metrics" => [3, 25.0, 450.0, 60.0]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [2, 50.0, 50.0, 40.0]}
]
end
test "returns top sources in realtime report", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
timestamp: relative_time(minute: -3)
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
timestamp: relative_time(minute: -2)
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
timestamp: relative_time(minute: -1)
)
])
response = query_sources(conn, site, date_range: "realtime")
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
end
test "can paginate the results", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
),
build(:imported_sources,
source: "DuckDuckGo"
),
build(:imported_sources,
source: "DuckDuckGo"
)
])
response1 =
query_sources(conn, site, date_range: "day", pagination: %{"limit" => 1, "offset" => 1})
assert response1["results"] == [
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
response2 =
query_sources(conn, site,
date_range: "day",
pagination: %{"limit" => 1, "offset" => 1},
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]}
]
end
test "shows sources for a page", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, pathname: "/page1", referrer_source: "Google"),
build(:pageview, pathname: "/page1", referrer_source: "Google"),
build(:pageview,
user_id: 1,
pathname: "/page2",
referrer_source: "DuckDuckGo"
),
build(:pageview,
user_id: 1,
pathname: "/page1",
referrer_source: "DuckDuckGo"
)
])
response =
query_sources(conn, site,
date_range: "day",
filters: [["is", "event:page", ["/page1"]]]
)
assert response["results"] == [
%{"dimensions" => ["Google"], "metrics" => [2, 66.67]},
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 33.33]}
]
end
test "order_by [[visit:source, desc]] is respected", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, referrer_source: "C"),
build(:pageview, referrer_source: "A"),
build(:pageview, referrer_source: "B")
])
response =
query_sources(conn, site,
date_range: "day",
order_by: [["visit:source", "desc"]]
)
assert response["results"] == [
%{"dimensions" => ["C"], "metrics" => [1, 33.33]},
%{"dimensions" => ["B"], "metrics" => [1, 33.33]},
%{"dimensions" => ["A"], "metrics" => [1, 33.33]}
]
end
test "order_by [[visit_duration, asc], [visit:source, desc]]] is respected and flipping the sort orders works",
%{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
pathname: "/in",
user_id: @user_id,
referrer_source: "B",
timestamp: ~N[2024-08-10 09:00:00]
),
build(:pageview,
pathname: "/out",
user_id: @user_id,
referrer_source: "B",
timestamp: ~N[2024-08-10 09:00:45]
),
build(:pageview,
pathname: "/in",
user_id: @user_id,
referrer_source: "C",
timestamp: ~N[2024-08-10 10:00:00]
),
build(:pageview,
pathname: "/out",
user_id: @user_id,
referrer_source: "C",
timestamp: ~N[2024-08-10 10:00:30]
),
build(:pageview, referrer_source: "A", timestamp: ~N[2024-08-10 10:00:30]),
build(:pageview, referrer_source: "A", timestamp: ~N[2024-08-10 10:00:30]),
build(:pageview, referrer_source: "Z", timestamp: ~N[2024-08-10 10:00:30])
])
response1 =
query_sources(conn, site,
date_range: ["2024-08-10", "2024-08-10"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
order_by: [["visit_duration", "asc"], ["visit:source", "desc"]]
)
assert response1["results"] == [
%{"dimensions" => ["Z"], "metrics" => [1, 100, 0, 25.0]},
%{"dimensions" => ["A"], "metrics" => [2, 100, 0, 50.0]},
%{"dimensions" => ["C"], "metrics" => [1, 0, 30, 25.0]},
%{"dimensions" => ["B"], "metrics" => [1, 0, 45, 25.0]}
]
response2 =
query_sources(conn, site,
date_range: ["2024-08-10", "2024-08-10"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
order_by: [["visit_duration", "desc"], ["visit:source", "asc"]]
)
assert response2["results"] == [
%{"dimensions" => ["B"], "metrics" => [1, 0, 45, 25.0]},
%{"dimensions" => ["C"], "metrics" => [1, 0, 30, 25.0]},
%{"dimensions" => ["A"], "metrics" => [2, 100, 0, 50.0]},
%{"dimensions" => ["Z"], "metrics" => [1, 100, 0, 25.0]}
]
end
test "can compare with previous period", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
timestamp: ~N[2021-01-02 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
timestamp: ~N[2021-01-02 00:00:00]
),
build(:pageview,
referrer_source: "Google",
referrer: "google.com",
timestamp: ~N[2021-01-02 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-02", "2021-01-02"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
include: %{"compare" => "previous_period"}
)
assert response["results"] == [
%{
"dimensions" => ["Google"],
"metrics" => [2, 100, 0, 66.67],
"comparison" => %{
"dimensions" => ["Google"],
"metrics" => [0, 0, nil, 0.0],
"change" => [100, nil, nil, 100]
}
},
%{
"dimensions" => ["DuckDuckGo"],
"metrics" => [1, 100, 0, 33.33],
"comparison" => %{
"dimensions" => ["DuckDuckGo"],
"metrics" => [1, 100, 0, 100.0],
"change" => [0, 0, 0, -67]
}
}
]
assert response["query"]["date_range"] == [
"2021-01-02T00:00:00Z",
"2021-01-02T23:59:59Z"
]
assert response["query"]["comparison_date_range"] == [
"2021-01-01T00:00:00Z",
"2021-01-01T23:59:59Z"
]
end
@tag :ee_only
test "return revenue metrics for sources breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
referrer_source: "Google",
referrer: "google.com"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
referrer_source: "Google",
referrer: "google.com"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
user_id: 4,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
),
build(:pageview,
user_id: 8,
referrer_source: "Bing",
referrer: "bing.com"
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]]],
order_by: [["visitors", "desc"], ["visit:source", "asc"]]
)
assert response["results"] == [
%{
"dimensions" => ["Direct / None"],
"metrics" => [
2,
100.0,
2,
%{
"currency" => "USD",
"long" => "$600.00",
"short" => "$600.0",
"value" => 600.0
},
%{
"currency" => "USD",
"long" => "$600.00",
"short" => "$600.0",
"value" => 600.0
}
]
},
%{
"dimensions" => ["Google"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["DuckDuckGo"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "UTM parameters with hostname filter" do
setup [:create_user, :log_in, :create_site]
for {resource, attr, dimension} <- [
{:utm_campaigns, :utm_campaign, "visit:utm_campaign"},
{:utm_sources, :utm_source, "visit:utm_source"},
{:utm_terms, :utm_term, "visit:utm_term"},
{:utm_contents, :utm_content, "visit:utm_content"}
] do
test "returns #{resource} when filtered by hostname", %{conn: conn, site: site} do
populate_stats(site, [
# session starts at two.example.com with utm_param=ad
build(
:pageview,
[
{unquote(attr), "ad"},
{:user_id, @user_id},
{:hostname, "two.example.com"},
{:timestamp, ~N[2021-01-01 00:00:00]}
]
),
# session continues on one.example.com without any utm_params
build(
:pageview,
[
{:user_id, @user_id},
{:hostname, "one.example.com"},
{:timestamp, ~N[2021-01-01 00:15:00]}
]
)
])
response =
query_sources(conn, site,
dimensions: [unquote(dimension)],
date_range: ["2021-01-01", "2021-01-01"],
filters: [["is", "event:hostname", ["one.example.com"]]]
)
# nobody landed on one.example.com from utm_param=ad
assert response["results"] == []
end
end
end
describe "GET /api/stats/:domain/channels" do
setup [:create_user, :log_in, :create_site]
test "returns top channels by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "Bing",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Bing",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
referrer_source: "Facebook",
utm_source: "fb-ads",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "Facebook",
utm_source: "fb-ads",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
dimensions: ["visit:channel"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response["results"] == [
%{"dimensions" => ["Paid Social"], "metrics" => [2, 100, 0, 66.67]},
%{"dimensions" => ["Organic Search"], "metrics" => [1, 0, 900, 33.33]}
]
end
@tag :ee_only
test "return revenue metrics for channels breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
referrer_source: "Google",
referrer: "google.com"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
referrer_source: "Google",
referrer: "google.com"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
referrer_source: "Google",
referrer: "google.com"
),
build(:pageview,
user_id: 4,
referrer_source: "Facebook",
utm_source: "fb-ads"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
referrer_source: "Facebook",
utm_source: "fb-ads"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:channel"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]]],
order_by: [["visitors", "desc"], ["visit:channel", "asc"]]
)
assert response["results"] == [
%{
"dimensions" => ["Direct"],
"metrics" => [
2,
100.0,
2,
%{
"currency" => "USD",
"long" => "$600.00",
"short" => "$600.0",
"value" => 600.0
},
%{
"currency" => "USD",
"long" => "$600.00",
"short" => "$600.0",
"value" => 600.0
}
]
},
%{
"dimensions" => ["Organic Search"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["Paid Social"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/utm_mediums" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top utm_mediums by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_medium: "social",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_medium: "social",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_medium: "email",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 800,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_medium: "social",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_medium: "email",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 100
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_medium"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"],
order_by: [["visit:utm_medium", "asc"]]
)
assert response1["results"] == [
%{"dimensions" => ["email"], "metrics" => [1, 100, 0, 50.0]},
%{"dimensions" => ["social"], "metrics" => [1, 0, 900, 50.0]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_medium"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"],
order_by: [["visit:utm_medium", "asc"]],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["email"], "metrics" => [2, 50, 50, 50.0]},
%{"dimensions" => ["social"], "metrics" => [2, 50, 800.0, 50.0]}
]
end
test "filters out entries without utm_medium present", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_medium: "social",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_medium: "social",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_medium: "",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 800,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_medium: "social",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_medium: "",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 100
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_medium"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_medium", [""]]],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["social"], "metrics" => [1, 0, 900, 100.0]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_medium"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_medium", [""]]],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["social"], "metrics" => [2, 50.0, 800.0, 100.0]}
]
end
@tag :ee_only
test "return revenue metrics for UTM mediums breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
utm_medium: "social"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
utm_medium: "social"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
utm_medium: "social"
),
build(:pageview,
user_id: 4,
utm_medium: "email"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
utm_medium: "email"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:utm_medium"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]], ["is_not", "visit:utm_medium", [""]]],
order_by: [["visitors", "desc"]]
)
assert response["results"] == [
%{
"dimensions" => ["social"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["email"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/utm_campaigns" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top utm_campaigns by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_campaign: "profile",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_campaign: "profile",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_campaign: "august",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_campaign: "august",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_campaign: "profile",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_campaign: "august",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_campaign"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["august"], "metrics" => [2, 100, 0, 66.67]},
%{"dimensions" => ["profile"], "metrics" => [1, 0, 900, 33.33]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_campaign"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["august"], "metrics" => [3, 67, 300, 60.0]},
%{"dimensions" => ["profile"], "metrics" => [2, 50, 800.0, 40.0]}
]
end
test "filters out entries without utm_campaign present", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_campaign: "profile",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_campaign: "profile",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_campaign: "",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_campaign: "",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_campaign: "profile",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_campaign: "",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_campaign"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_campaign", [""]]],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["profile"], "metrics" => [1, 0, 900, 100.0]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_campaign"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_campaign", [""]]],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["profile"], "metrics" => [2, 50.0, 800.0, 100.0]}
]
end
@tag :ee_only
test "return revenue metrics for UTM campaigns breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
utm_campaign: "profile"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
utm_campaign: "profile"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
utm_campaign: "profile"
),
build(:pageview,
user_id: 4,
utm_campaign: "august"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
utm_campaign: "august"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:utm_campaign"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]], ["is_not", "visit:utm_campaign", [""]]],
order_by: [["visitors", "desc"]]
)
assert response["results"] == [
%{
"dimensions" => ["profile"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["august"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/utm_sources" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top utm_sources by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_source: "Twitter",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_source: "Twitter",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_source: "newsletter",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_source: "newsletter",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
dimensions: ["visit:utm_source"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response["results"] == [
%{"dimensions" => ["newsletter"], "metrics" => [2, 100, 0, 66.67]},
%{"dimensions" => ["Twitter"], "metrics" => [1, 0, 900, 33.33]}
]
end
@tag :ee_only
test "return revenue metrics for UTM sources breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
utm_source: "Twitter"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
utm_source: "Twitter"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
utm_source: "Twitter"
),
build(:pageview,
user_id: 4,
utm_source: "newsletter"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
utm_source: "newsletter"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:utm_source"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]], ["is_not", "visit:utm_source", [""]]],
order_by: [["visitors", "desc"]]
)
assert response["results"] == [
%{
"dimensions" => ["Twitter"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["newsletter"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/utm_terms" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top utm_terms by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_term: "oat milk",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_term: "oat milk",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_term: "Sweden",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_term: "Sweden",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_term: "oat milk",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_term: "Sweden",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_term"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["Sweden"], "metrics" => [2, 100, 0, 66.67]},
%{"dimensions" => ["oat milk"], "metrics" => [1, 0, 900, 33.33]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_term"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["Sweden"], "metrics" => [3, 67.0, 300.0, 60.0]},
%{"dimensions" => ["oat milk"], "metrics" => [2, 50.0, 800.0, 40.0]}
]
end
test "filters out entries without utm_term present", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_term: "oat milk",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_term: "oat milk",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_term: "",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_term: "",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_term: "oat milk",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_term: "",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_term"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_term", [""]]],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["oat milk"], "metrics" => [1, 0, 900, 100.0]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_term"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_term", [""]]],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["oat milk"], "metrics" => [2, 50.0, 800.0, 100.0]}
]
end
@tag :ee_only
test "return revenue metrics for UTM terms breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
utm_term: "oat milk"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
utm_term: "oat milk"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
utm_term: "oat milk"
),
build(:pageview,
user_id: 4,
utm_term: "Sweden"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
utm_term: "Sweden"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:utm_term"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]], ["is_not", "visit:utm_term", [""]]],
order_by: [["visitors", "desc"]]
)
assert response["results"] == [
%{
"dimensions" => ["oat milk"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["Sweden"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/utm_contents" do
setup [:create_user, :log_in, :create_site, :create_legacy_site_import]
test "returns top utm_contents by unique user ids", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_content: "ad",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_content: "ad",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_content: "blog",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_content: "blog",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_content: "ad",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_content: "blog",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_content"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["blog"], "metrics" => [2, 100, 0, 66.67]},
%{"dimensions" => ["ad"], "metrics" => [1, 0, 900, 33.33]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_content"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["blog"], "metrics" => [3, 67.0, 300.0, 60.0]},
%{"dimensions" => ["ad"], "metrics" => [2, 50.0, 800.0, 40.0]}
]
end
test "filters out entries without utm_content present", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
utm_content: "ad",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_content: "ad",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
utm_content: "",
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
utm_content: "",
timestamp: ~N[2021-01-01 00:00:00]
)
])
populate_stats(site, [
build(:imported_visitors,
date: ~D[2021-01-01],
visit_duration: 1600,
bounces: 1,
visits: 2,
visitors: 2
),
build(:imported_sources,
utm_content: "ad",
date: ~D[2021-01-01],
visit_duration: 700,
bounces: 1,
visits: 1,
visitors: 1
),
build(:imported_sources,
utm_content: "",
date: ~D[2021-01-01],
bounces: 0,
visits: 1,
visitors: 1,
visit_duration: 900
)
])
response1 =
query_sources(conn, site,
dimensions: ["visit:utm_content"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_content", [""]]],
date_range: ["2021-01-01", "2021-01-01"]
)
assert response1["results"] == [
%{"dimensions" => ["ad"], "metrics" => [1, 0, 900, 100.0]}
]
response2 =
query_sources(conn, site,
dimensions: ["visit:utm_content"],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"],
filters: [["is_not", "visit:utm_content", [""]]],
date_range: ["2021-01-01", "2021-01-01"],
include: %{"imports" => true}
)
assert response2["results"] == [
%{"dimensions" => ["ad"], "metrics" => [2, 50.0, 800.0, 100.0]}
]
end
@tag :ee_only
test "return revenue metrics for UTM contents breakdown", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
user_id: 1,
utm_content: "ad"
),
build(:event,
name: "Payment",
user_id: 1,
revenue_reporting_amount: Decimal.new("1000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 2,
utm_content: "ad"
),
build(:event,
name: "Payment",
user_id: 2,
revenue_reporting_amount: Decimal.new("2000"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 3,
utm_content: "ad"
),
build(:pageview,
user_id: 4,
utm_content: "blog"
),
build(:event,
name: "Payment",
user_id: 4,
revenue_reporting_amount: Decimal.new("500"),
revenue_reporting_currency: "USD"
),
build(:pageview,
user_id: 5,
utm_content: "blog"
),
build(:pageview, user_id: 6),
build(:event,
name: "Payment",
user_id: 6,
revenue_reporting_amount: Decimal.new("600"),
revenue_reporting_currency: "USD"
),
build(:pageview, user_id: 7),
build(:event,
name: "Payment",
user_id: 7,
revenue_reporting_amount: nil
)
])
insert(:goal, %{site: site, event_name: "Payment", currency: :USD})
response =
query_sources(conn, site,
dimensions: ["visit:utm_content"],
date_range: "day",
metrics: [
"visitors",
"group_conversion_rate",
"total_visitors",
"average_revenue",
"total_revenue"
],
filters: [["is", "event:goal", ["Payment"]], ["is_not", "visit:utm_content", [""]]],
order_by: [["visitors", "desc"]]
)
assert response["results"] == [
%{
"dimensions" => ["ad"],
"metrics" => [
2,
66.67,
3,
%{
"currency" => "USD",
"long" => "$1,500.00",
"short" => "$1.5K",
"value" => 1500.0
},
%{
"currency" => "USD",
"long" => "$3,000.00",
"short" => "$3.0K",
"value" => 3000.0
}
]
},
%{
"dimensions" => ["blog"],
"metrics" => [
1,
50.0,
2,
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
},
%{
"currency" => "USD",
"long" => "$500.00",
"short" => "$500.0",
"value" => 500.0
}
]
}
]
end
end
describe "GET /api/stats/:domain/sources - with goal filter" do
setup [:create_user, :log_in, :create_site]
test "returns top referrers for a custom goal including conversion_rate", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "Twitter",
user_id: @user_id
),
build(:event,
name: "Signup",
user_id: @user_id
),
build(:pageview,
referrer_source: "Twitter"
)
])
# Imported data is ignored when filtering
populate_stats(site, [
build(:imported_sources, source: "Twitter")
])
insert(:goal, site: site, event_name: "Signup")
response =
query_sources(conn, site,
date_range: "day",
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [["is", "event:goal", ["Signup"]]]
)
assert response["results"] == [
%{"dimensions" => ["Twitter"], "metrics" => [1, 50.0, 2]}
]
end
test "returns no top referrers for a custom goal and filtered by hostname",
%{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
hostname: "blog.example.com",
referrer_source: "Facebook",
user_id: @user_id
),
build(:pageview,
hostname: "app.example.com",
pathname: "/register",
user_id: @user_id
),
build(:event,
name: "Signup",
hostname: "app.example.com",
pathname: "/register",
user_id: @user_id
)
])
response =
query_sources(conn, site,
date_range: "day",
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [
["is", "event:goal", ["Signup"]],
["is", "event:hostname", ["app.example.com"]]
]
)
assert response["results"] == []
end
test "returns top referrers for a custom goal and filtered by hostname (2)",
%{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
hostname: "app.example.com",
referrer_source: "Facebook",
pathname: "/register",
user_id: @user_id
),
build(:event,
name: "Signup",
hostname: "app.example.com",
pathname: "/register",
user_id: @user_id
)
])
insert(:goal, site: site, event_name: "Signup")
response =
query_sources(conn, site,
date_range: "day",
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [
["is", "event:goal", ["Signup"]],
["is", "event:hostname", ["app.example.com"]]
]
)
assert response["results"] == [
%{"dimensions" => ["Facebook"], "metrics" => [1, 100.0, 1]}
]
end
test "returns top referrers with goal filter + :is prop filter", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:event,
name: "Download",
"meta.key": ["method", "logged_in"],
"meta.value": ["HTTP", "true"],
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
"meta.key": ["logged_in"],
"meta.value": ["true"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:event,
referrer_source: "Facebook",
referrer: "facebook.com",
name: "Download",
"meta.key": ["method", "logged_in"],
"meta.value": ["HTTP", "false"],
timestamp: ~N[2021-01-01 00:00:00]
)
])
insert(:goal, site: site, event_name: "Download")
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [
["is", "event:goal", ["Download"]],
["is", "event:props:logged_in", ["true"]]
]
)
assert response["results"] == [
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 50.0, 2]}
]
end
test "returns top referrers with goal filter + prop :is_not filter", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "DuckDuckGo",
referrer: "duckduckgo.com",
user_id: 123,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:event,
name: "Download",
"meta.key": ["method"],
"meta.value": ["HTTP"],
user_id: 123,
timestamp: ~N[2021-01-01 00:01:00]
),
build(:event,
name: "Download",
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["method", "logged_in"],
"meta.value": ["HTTP", "true"],
timestamp: ~N[2021-01-01 00:00:00]
),
build(:event,
name: "Download",
referrer_source: "Google",
referrer: "google.com",
"meta.key": ["method", "logged_in"],
"meta.value": ["HTTP", "false"],
timestamp: ~N[2021-01-01 00:00:00]
)
])
insert(:goal, site: site, event_name: "Download")
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [
["is", "event:goal", ["Download"]],
["is_not", "event:props:logged_in", ["true"]]
],
order_by: [["visit:source", "asc"]]
)
assert response["results"] == [
%{"dimensions" => ["DuckDuckGo"], "metrics" => [1, 100.0, 1]},
%{"dimensions" => ["Google"], "metrics" => [1, 50.0, 2]}
]
end
test "returns top referrers for a pageview goal including conversion_rate", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "Twitter",
user_id: @user_id
),
build(:pageview,
pathname: "/register",
user_id: @user_id
),
build(:pageview,
referrer_source: "Twitter"
)
])
insert(:goal, site: site, page_path: "/register")
response =
query_sources(conn, site,
date_range: "day",
metrics: ["visitors", "group_conversion_rate", "total_visitors"],
filters: [["is", "event:goal", ["Visit /register"]]]
)
assert response["results"] == [
%{"dimensions" => ["Twitter"], "metrics" => [1, 50.0, 2]}
]
end
end
describe "GET /api/stats/:domain/referrer-drilldown (Google Search Terms)" do
setup [:create_user, :log_in, :create_site]
test "gets keywords from Google", %{conn: conn, site: site} do
conn = get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day")
assert %{
"results" => [
%{
"name" => "simple web analytics",
"visitors" => 25,
"impressions" => 50,
"position" => 2.0,
"ctr" => 37.0
},
%{
"name" => "open-source analytics",
"visitors" => 15,
"impressions" => 25,
"position" => 4.0,
"ctr" => 50.0
}
]
} = json_response(conn, 200)
end
test "returns 200 with empty keywords list when no data returned from last 30d", %{
conn: conn,
site: site
} do
filters = Jason.encode!([[:is, "event:page", ["/empty"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=30d&filters=#{filters}")
assert json_response(conn, 200) == %{"results" => []}
end
test "returns 422 with error when no data returned and queried range is too recent", %{
conn: conn,
site: site
} do
filters = Jason.encode!([[:is, "event:page", ["/empty"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day&filters=#{filters}")
assert json_response(conn, 422) == %{"error_code" => "period_too_recent"}
end
test "returns 422 with error when Google account not connected (admin)", %{
conn: conn,
site: site
} do
filters = Jason.encode!([[:is, "event:page", ["/not-configured"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day&filters=#{filters}")
assert %{"error_code" => "not_configured", "is_admin" => true} = json_response(conn, 422)
end
test "returns 422 with error when Google account not connected (non-admin)", %{conn: conn} do
site = new_site(public: true)
filters = Jason.encode!([[:is, "event:page", ["/not-configured"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day&filters=#{filters}")
%{
"error_code" => "not_configured",
"is_admin" => false
} = json_response(conn, 422)
end
test "returns 422 with error when unsupported filters used", %{conn: conn, site: site} do
filters = Jason.encode!([[:is, "event:page", ["/unsupported-filters"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day&filters=#{filters}")
assert %{"error_code" => "unsupported_filters"} = json_response(conn, 422)
end
@tag :capture_log
test "returns 502 when Google API responds with an unexpected error", %{
conn: conn,
site: site
} do
filters = Jason.encode!([[:is, "event:page", ["/unexpected-error"]]])
conn =
get(conn, "/api/stats/#{site.domain}/google-search-terms?period=day&filters=#{filters}")
assert %{"error_code" => "not_configured"} = json_response(conn, 502)
end
end
describe "GET /api/stats/:domain/referrer-drilldown" do
setup [:create_user, :log_in, :create_site]
test "returns top referrers for a particular source", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "10words",
referrer: "10words.com"
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com"
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com/page1"
),
build(:pageview,
referrer_source: "ignored",
referrer: "ignored"
)
])
response =
query_sources(conn, site,
date_range: "day",
dimensions: ["visit:referrer"],
filters: [["is", "visit:source", ["10words"]]]
)
assert response["results"] == [
%{"dimensions" => ["10words.com"], "metrics" => [2, 66.67]},
%{"dimensions" => ["10words.com/page1"], "metrics" => [1, 33.33]}
]
end
test "returns top referrers for a particular source filtered by hostname", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview,
referrer_source: "example",
referrer: "example.com",
hostname: "two.example.com"
),
build(:pageview,
referrer_source: "example",
referrer: "example.com",
hostname: "two.example.com",
user_id: @user_id
),
build(:pageview,
hostname: "one.example.com",
user_id: @user_id
),
build(:pageview,
referrer_source: "example",
referrer: "example.com/page1",
hostname: "one.example.com"
),
build(:pageview,
referrer_source: "ignored",
referrer: "ignored",
hostname: "two.example.com"
)
])
response =
query_sources(conn, site,
date_range: "day",
dimensions: ["visit:referrer"],
filters: [
["is", "visit:source", ["example"]],
["is", "event:hostname", ["one.example.com"]]
]
)
assert response["results"] == [
%{"dimensions" => ["example.com/page1"], "metrics" => [1, 100.0]}
]
end
test "calculates bounce rate and visit duration for referrer urls", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "10words",
referrer: "10words.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:00:00]
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com",
user_id: @user_id,
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com",
timestamp: ~N[2021-01-01 00:15:00]
),
build(:pageview,
referrer_source: "ignored",
referrer: "ignored",
timestamp: ~N[2021-01-01 00:00:00]
)
])
response =
query_sources(conn, site,
date_range: ["2021-01-01", "2021-01-01"],
dimensions: ["visit:referrer"],
filters: [["is", "visit:source", ["10words"]]],
metrics: ["visitors", "bounce_rate", "visit_duration", "percentage"]
)
assert response["results"] == [
%{"dimensions" => ["10words.com"], "metrics" => [2, 50.0, 450, 100.0]}
]
end
test "returns top referring urls for a custom goal", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "10words",
referrer: "10words.com"
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com",
user_id: @user_id
),
build(:event,
name: "Signup",
user_id: @user_id
),
build(:event,
name: "Signup"
)
])
insert(:goal, site: site, event_name: "Signup")
response =
query_sources(conn, site,
date_range: "day",
dimensions: ["visit:referrer"],
filters: [
["is", "visit:source", ["10words"]],
["is", "event:goal", ["Signup"]]
],
metrics: ["visitors", "total_visitors", "group_conversion_rate"]
)
assert response["results"] == [
%{"dimensions" => ["10words.com"], "metrics" => [1, 2, 50.0]}
]
end
test "returns top referring urls for a pageview goal", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview,
referrer_source: "10words",
referrer: "10words.com"
),
build(:pageview,
referrer_source: "10words",
referrer: "10words.com",
user_id: @user_id
),
build(:pageview,
pathname: "/register",
user_id: @user_id
),
build(:pageview,
pathname: "/register"
)
])
insert(:goal, site: site, page_path: "/register")
response =
query_sources(conn, site,
date_range: "day",
dimensions: ["visit:referrer"],
filters: [
["is", "visit:source", ["10words"]],
["is", "event:goal", ["Visit /register"]]
],
metrics: ["visitors", "total_visitors", "group_conversion_rate"]
)
assert response["results"] == [
%{"dimensions" => ["10words.com"], "metrics" => [1, 2, 50.0]}
]
end
end
end