Show total visitors when filtered for goal

This commit is contained in:
Uku Taht 2021-09-29 13:28:29 +02:00
parent 4c77df477f
commit bd7de59a9c
19 changed files with 224 additions and 52 deletions

View File

@ -22,7 +22,15 @@ class CountriesModal extends React.Component {
}
label() {
return this.state.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
showConversionRate() {
@ -48,8 +56,9 @@ class CountriesModal extends React.Component {
{countryFullName}
</Link>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{country.total_visitors}</td> }
<td className="p-2 w-32 font-medium" align="right">
{numberFormatter(country.count)} <span className="inline-block text-xs w-8 text-right">({country.percentage}%)</span>
{numberFormatter(country.count)} {!this.showConversionRate() && <span className="inline-block text-xs w-8 text-right">({country.percentage}%)</span>}
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{country.conversion_rate}%</td> }
</tr>
@ -79,6 +88,7 @@ class CountriesModal extends React.Component {
>
Country
</th>
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total visitors</th>}
<th
// eslint-disable-next-line max-len
className="p-2 w-32 lg:w-1/2 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400"

View File

@ -45,10 +45,6 @@ class EntryPagesModal extends React.Component {
this.setState({loading: true, page: page + 1}, this.loadPages.bind(this))
}
showVisitDuration() {
return this.state.query.period !== 'realtime'
}
formatBounceRate(page) {
if (typeof(page.bounce_rate) === 'number') {
return `${page.bounce_rate}%`;
@ -60,6 +56,22 @@ class EntryPagesModal extends React.Component {
return !!this.state.query.filters.goal
}
showExtra() {
return this.state.query.period !== 'realtime' && !this.showConversionRate()
}
label() {
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderPage(page) {
const query = new URLSearchParams(window.location.search)
query.set('entry_page', page.name)
@ -77,9 +89,10 @@ class EntryPagesModal extends React.Component {
{page.name}
</Link>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.total_visitors)}</td>}
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.count)}</td>
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.entries)}</td>
{this.showVisitDuration() && <td className="p-2 w-32 font-medium" align="right">{durationFormatter(page.visit_duration)}</td>}
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.entries)}</td>}
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{durationFormatter(page.visit_duration)}</td>}
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.conversion_rate)}%</td>}
</tr>
)
@ -115,26 +128,11 @@ class EntryPagesModal extends React.Component {
align="left"
>Page url
</th>
<th
className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400"
align="right"
>Unique Entrances
</th>
<th
className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400"
align="right"
>Total Entrances
</th>
<th
className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400"
align="right"
>Visit Duration
</th>
{this.showConversionRate() && <th
className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400"
align="right"
>CR
</th>}
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >Total Visitors </th>}
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >{this.label()} </th>
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >Total Entrances </th> }
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >Visit Duration </th> }
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >CR </th>}
</tr>
</thead>
<tbody>

View File

@ -46,6 +46,22 @@ class ExitPagesModal extends React.Component {
return !!this.state.query.filters.goal
}
showExtra() {
return this.state.query.period !== 'realtime' && !this.showConversionRate()
}
label() {
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderPage(page) {
const query = new URLSearchParams(window.location.search)
query.set('exit_page', page.name)
@ -55,9 +71,10 @@ class ExitPagesModal extends React.Component {
<td className="p-2">
<Link to={{pathname: `/${encodeURIComponent(this.props.site.domain)}`, search: query.toString()}} className="hover:underline">{page.name}</Link>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.total_visitors)}</td>}
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.count)}</td>
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.exits)}</td>
<td className="p-2 w-32 font-medium" align="right">{this.formatPercentage(page.exit_rate)}</td>
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.exits)}</td>}
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatPercentage(page.exit_rate)}</td>}
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.conversion_rate)}%</td>}
</tr>
)
@ -89,9 +106,10 @@ class ExitPagesModal extends React.Component {
<thead>
<tr>
<th className="p-2 w-48 md:w-56 lg:w-1/3 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="left">Page url</th>
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Unique Exits</th>
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total Exits</th>
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Exit Rate</th>
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right" >Total Visitors </th>}
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">{this.label()}</th>
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total Exits</th>}
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Exit Rate</th>}
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">CR</th>}
</tr>
</thead>

View File

@ -66,6 +66,7 @@ class PagesModal extends React.Component {
<td className="p-2">
<Link to={{pathname: `/${encodeURIComponent(this.props.site.domain)}`, search: query.toString()}} className="hover:underline block truncate">{page.name}</Link>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{page.total_visitors}</td> }
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.count)}</td>
{this.showPageviews() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(page.pageviews)}</td> }
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatBounceRate(page)}</td> }
@ -76,7 +77,15 @@ class PagesModal extends React.Component {
}
label() {
return this.state.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderLoading() {
@ -105,6 +114,7 @@ class PagesModal extends React.Component {
<thead>
<tr>
<th className="p-2 w-48 md:w-56 lg:w-1/3 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="left">Page url</th>
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total visitors</th>}
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">{ this.label() }</th>
{this.showPageviews() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Pageviews</th>}
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Bounce rate</th>}

View File

@ -27,6 +27,22 @@ class ReferrerDrilldownModal extends React.Component {
return this.state.query.period !== 'realtime' && !this.state.query.filters.goal
}
showConversionRate() {
return !!this.state.query.filters.goal
}
label() {
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
formatBounceRate(ref) {
if (typeof(ref.bounce_rate) === 'number') {
return ref.bounce_rate + '%'
@ -107,9 +123,11 @@ class ReferrerDrilldownModal extends React.Component {
{ referrer.tweets.map(this.renderTweet) }
</div>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(referrer.total_visitors)}</td> }
<td className="p-2 w-32 font-medium" align="right" valign="top">{numberFormatter(referrer.count)}</td>
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right" valign="top">{this.formatBounceRate(referrer)}</td> }
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right" valign="top">{this.formatDuration(referrer)}</td> }
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{referrer.conversion_rate}%</td> }
</tr>
)
} else {
@ -118,9 +136,11 @@ class ReferrerDrilldownModal extends React.Component {
<td className="p-2">
{ this.renderReferrerName(referrer) }
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(referrer.total_visitors)}</td> }
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(referrer.count)}</td>
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatBounceRate(referrer)}</td> }
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatDuration(referrer)}</td> }
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{referrer.conversion_rate}%</td> }
</tr>
)
}
@ -153,9 +173,11 @@ class ReferrerDrilldownModal extends React.Component {
<thead>
<tr>
<th className="p-2 w-48 md:w-56 lg:w-1/3 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="left">Referrer</th>
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Visitors</th>
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total visitors</th>}
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">{this.label()}</th>
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Bounce rate</th>}
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Visit duration</th>}
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">CR</th>}
</tr>
</thead>
<tbody>

View File

@ -97,6 +97,7 @@ class SourcesModal extends React.Component {
/>
<Link className="hover:underline" to={{search: query.toString(), pathname: '/' + encodeURIComponent(this.props.site.domain)}}>{ source.name }</Link>
</td>
{this.showConversionRate() && <td className="p-2 w-32 font-medium" align="right">{numberFormatter(source.total_visitors)}</td> }
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(source.count)}</td>
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatBounceRate(source)}</td> }
{this.showExtra() && <td className="p-2 w-32 font-medium" align="right">{this.formatDuration(source)}</td> }
@ -106,7 +107,15 @@ class SourcesModal extends React.Component {
}
label() {
return this.state.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.state.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderLoading() {
@ -139,6 +148,7 @@ class SourcesModal extends React.Component {
<thead>
<tr>
<th className="p-2 w-48 md:w-56 lg:w-1/3 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="left">Source</th>
{this.showConversionRate() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Total visitors</th>}
<th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">{this.label()}</th>
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Bounce rate</th>}
{this.showExtra() && <th className="p-2 w-32 text-xs tracking-wide font-bold text-gray-500 dark:text-gray-400" align="right">Visit duration</th>}

View File

@ -38,6 +38,18 @@ export default class EntryPages extends React.Component {
.then((res) => this.setState({loading: false, pages: res}))
}
label() {
if (this.props.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Unique Entrances'
}
renderPage(page) {
const externalLink = url.externalLinkForPage(this.props.site.domain, page.name)
const maxWidthDeduction = this.showConversionRate() ? "10rem" : "5rem"
@ -80,7 +92,7 @@ export default class EntryPages extends React.Component {
<div className="flex items-center justify-between mt-3 mb-2 text-xs font-bold tracking-wide text-gray-500 dark:text-gray-400">
<span>Page url</span>
<div className="text-right">
<span className="inline-block w-30">Unique Entrances</span>
<span className="inline-block w-30">{this.label()}</span>
{this.showConversionRate() && <span className="inline-block w-20">CR</span>}
</div>
</div>

View File

@ -33,6 +33,18 @@ export default class ExitPages extends React.Component {
return !!this.props.query.filters.goal
}
label() {
if (this.props.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Unique Exits'
}
fetchPages() {
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/exit-pages`, this.props.query)
.then((res) => this.setState({loading: false, pages: res}))
@ -80,7 +92,7 @@ export default class ExitPages extends React.Component {
<div className="flex items-center justify-between mt-3 mb-2 text-xs font-bold tracking-wide text-gray-500 dark:text-gray-400">
<span>Page url</span>
<div className="text-right">
<span className="inline-block w-20">Unique Exits</span>
<span className="inline-block w-20">{this.label()}</span>
{this.showConversionRate() && <span className="inline-block w-20">CR</span>}
</div>
</div>

View File

@ -43,6 +43,10 @@ export default class Visits extends React.Component {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}

View File

@ -41,6 +41,10 @@ export default class Referrers extends React.Component {
return this.props.query.period === 'realtime'
}
showConversionRate() {
return !!this.props.query.filters.goal
}
fetchReferrers() {
if (this.props.query.filters.source) {
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/${encodeURIComponent(this.props.query.filters.source)}`, this.props.query, {show_noref: this.showNoRef()})
@ -67,6 +71,7 @@ export default class Referrers extends React.Component {
}
renderReferrer(referrer) {
const maxWidthDeduction = this.showConversionRate() ? "10rem" : "5rem"
const query = new URLSearchParams(window.location.search)
query.set('referrer', referrer.name)
@ -76,7 +81,7 @@ export default class Referrers extends React.Component {
count={referrer.count}
all={this.state.referrers}
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem"
maxWidthDeduction={maxWidthDeduction}
>
<span className="flex px-2 py-1.5 z-9 relative break-all group">
<LinkOption
@ -85,7 +90,7 @@ export default class Referrers extends React.Component {
disabled={referrer.name === 'Direct / None'}
>
<img
src={`https://icons.duckduckgo.com/ip3/${referrer.url}.ico`}
src={`/favicon/sources/${encodeURIComponent(referrer.name)}`}
referrerPolicy="no-referrer"
className="inline w-4 h-4 mr-2 -mt-px align-middle"
/>
@ -95,12 +100,21 @@ export default class Referrers extends React.Component {
</span>
</Bar>
<span className="font-medium dark:text-gray-200">{numberFormatter(referrer.count)}</span>
{this.showConversionRate() && <span className="font-medium dark:text-gray-200 w-20 text-right">{referrer.conversion_rate}%</span>}
</div>
)
}
label() {
return this.props.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.props.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderList() {
@ -108,10 +122,14 @@ export default class Referrers extends React.Component {
return (
<div className="flex flex-col flex-grow">
<div
className="flex items-center justify-between mt-3 mb-2 text-xs font-bold tracking-wide text-gray-500 dark:text-gray-400"
className="flex items-center justify-between mt-3 mb-2 text-xs font-bold tracking-wide text-gray-500"
>
<span>Referrer</span>
<span>{ this.label() }</span>
<div className="text-right">
<span className="inline-block w-20">{this.label()}</span>
{this.showConversionRate() && <span className="inline-block w-20">CR</span>}
</div>
</div>
<FlipMove className="flex-grow">

View File

@ -77,7 +77,15 @@ class AllSources extends React.Component {
}
label() {
return this.props.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.props.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderList() {
@ -198,7 +206,15 @@ class UTMSources extends React.Component {
}
label() {
return this.props.query.period === 'realtime' ? 'Current visitors' : 'Visitors'
if (this.props.query.period === 'realtime') {
return 'Current visitors'
}
if (this.showConversionRate()) {
return 'Conversions'
}
return 'Visitors'
}
renderList() {

View File

@ -311,6 +311,7 @@ defmodule Plausible.Stats.Base do
end
defp db_prop_val("referrer_source", @no_ref), do: ""
defp db_prop_val("referrer", @no_ref), do: ""
defp db_prop_val("utm_medium", @no_ref), do: ""
defp db_prop_val("utm_source", @no_ref), do: ""
defp db_prop_val("utm_campaign", @no_ref), do: ""

View File

@ -321,6 +321,7 @@ defmodule PlausibleWeb.Api.StatsController do
referrers =
Stats.breakdown(site, query, "visit:referrer", metrics, pagination)
|> maybe_add_cr(site, query, pagination, "referrer", "visit:referrer")
|> transform_keys(%{"referrer" => "name", "visitors" => "count"})
%{"visitors" => %{"value" => total_visitors}} = Stats.aggregate(site, query, ["visitors"])
@ -608,6 +609,7 @@ defmodule PlausibleWeb.Api.StatsController do
without_goal = Enum.find(list_without_goals, fn s -> s[key_name] === item[key_name] end)
item
|> Map.put(:total_visitors, without_goal["visitors"])
|> Map.put(:conversion_rate, calculate_cr(without_goal["visitors"], item["visitors"]))
end)
end

View File

@ -32,7 +32,13 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
conn = get(conn, "/api/stats/#{site.domain}/browsers?period=day&filters=#{filters}")
assert json_response(conn, 200) == [
%{"name" => "Chrome", "count" => 1, "percentage" => 100, "conversion_rate" => 50.0}
%{
"name" => "Chrome",
"total_visitors" => 2,
"count" => 1,
"percentage" => 100,
"conversion_rate" => 50.0
}
]
end
end

View File

@ -59,12 +59,14 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do
assert json_response(conn, 200) == [
%{
"name" => "GBR",
"total_visitors" => 1,
"count" => 1,
"percentage" => 50,
"conversion_rate" => 100.0
},
%{
"name" => "EST",
"total_visitors" => 2,
"count" => 1,
"percentage" => 50,
"conversion_rate" => 50.0

View File

@ -33,7 +33,13 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do
get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}")
assert json_response(conn, 200) == [
%{"name" => "Mac", "count" => 1, "percentage" => 100, "conversion_rate" => 50.0}
%{
"name" => "Mac",
"total_visitors" => 2,
"count" => 1,
"percentage" => 100,
"conversion_rate" => 50.0
}
]
end
end

View File

@ -95,7 +95,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}")
assert json_response(conn, 200) == [
%{"count" => 1, "name" => "/", "conversion_rate" => 33.3}
%{"total_visitors" => 3, "count" => 1, "name" => "/", "conversion_rate" => 33.3}
]
end
end
@ -195,6 +195,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
assert json_response(conn, 200) == [
%{
"total_visitors" => 1,
"count" => 1,
"entries" => 1,
"name" => "/page2",
@ -202,6 +203,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
"conversion_rate" => 100.0
},
%{
"total_visitors" => 2,
"count" => 1,
"entries" => 1,
"name" => "/page1",
@ -289,6 +291,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
%{
"name" => "/exit1",
"count" => 1,
"total_visitors" => 1,
"exits" => 1,
"exit_rate" => 50,
"conversion_rate" => 100.0
@ -296,6 +299,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
%{
"name" => "/exit2",
"count" => 1,
"total_visitors" => 1,
"exits" => 1,
"exit_rate" => 100,
"conversion_rate" => 100.0

View File

@ -34,6 +34,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do
assert json_response(conn, 200) == [
%{
"name" => "Desktop",
"total_visitors" => 2,
"count" => 1,
"percentage" => 100,
"conversion_rate" => 50.0

View File

@ -310,7 +310,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
)
assert json_response(conn, 200) == [
%{"name" => "Twitter", "count" => 1, "conversion_rate" => 50.0}
%{
"name" => "Twitter",
"total_visitors" => 2,
"count" => 1,
"conversion_rate" => 50.0
}
]
end
@ -341,7 +346,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
)
assert json_response(conn, 200) == [
%{"name" => "Twitter", "count" => 1, "conversion_rate" => 50.0}
%{
"name" => "Twitter",
"total_visitors" => 2,
"count" => 1,
"conversion_rate" => 50.0
}
]
end
end
@ -487,7 +497,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
assert json_response(conn, 200) == %{
"total_visitors" => 1,
"referrers" => [
%{"name" => "10words.com", "count" => 1}
%{
"name" => "10words.com",
"total_visitors" => 2,
"conversion_rate" => 50.0,
"count" => 1
}
]
}
end
@ -523,7 +538,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
assert json_response(conn, 200) == %{
"total_visitors" => 1,
"referrers" => [
%{"name" => "10words.com", "count" => 1}
%{
"name" => "10words.com",
"total_visitors" => 2,
"conversion_rate" => 50.0,
"count" => 1
}
]
}
end