mirror of
https://github.com/plausible/analytics.git
synced 2024-11-23 03:04:43 +03:00
Configurable site id (#30)
* Use site id instead of hostname for events * Use site id in domain status check * Revert change to tracking module * Catch more places where link generation needed updating * Rename site_id to domain * Drop hostname index from events
This commit is contained in:
parent
ccbc04f6bd
commit
7dbbc8ba22
@ -22,7 +22,7 @@ export default class Browsers extends React.Component {
|
||||
}
|
||||
|
||||
fetchBrowsers() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/browsers`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/browsers`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, browsers: res}))
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export default class Conversions extends React.Component {
|
||||
}
|
||||
|
||||
fetchConversions() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/conversions`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/conversions`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, goals: res}))
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export default class Countries extends React.Component {
|
||||
}
|
||||
|
||||
fetchCountries() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/countries`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/countries`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, countries: res}))
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ export default class CurrentVisitors extends React.Component {
|
||||
}
|
||||
|
||||
updateCount() {
|
||||
return fetch(`/api/stats/${this.props.site.domain}/current-visitors`)
|
||||
return fetch(`/api/stats/${encodeURIComponent(this.props.site.domain)}/current-visitors`)
|
||||
.then(res => res.json())
|
||||
.then((res) => this.setState({currentVisitors: res}))
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class BrowsersModal extends React.Component {
|
||||
componentDidMount() {
|
||||
const query = parseQuery(this.props.location.search, this.props.site)
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/browsers`, query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/browsers`, query, {limit: 100})
|
||||
.then((res) => this.setState({loading: false, browsers: res}))
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class CountriesModal extends React.Component {
|
||||
componentDidMount() {
|
||||
const query = parseQuery(this.props.location.search, this.props.site)
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/countries`, query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/countries`, query, {limit: 100})
|
||||
.then((res) => this.setState({loading: false, countries: res}))
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class GoogleKeywordsModal extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/referrers/Google`, this.state.query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/Google`, this.state.query, {limit: 100})
|
||||
.then((res) => this.setState({
|
||||
loading: false,
|
||||
searchTerms: res.search_terms,
|
||||
@ -56,7 +56,7 @@ class GoogleKeywordsModal extends React.Component {
|
||||
<RocketIcon />
|
||||
<div className="text-lg">The site is not connected to Google Search Keywords</div>
|
||||
<div className="text-lg">Configure the integration to view search terms</div>
|
||||
<a href={`/${this.props.site.domain}/settings#google-auth`} className="button mt-4">Connect with Google</a>
|
||||
<a href={`/${encodeURIComponent(this.props.site.domain)}/settings#google-auth`} className="button mt-4">Connect with Google</a>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
@ -93,7 +93,7 @@ class GoogleKeywordsModal extends React.Component {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<header className="modal__header">
|
||||
<Link to={`/${this.props.site.domain}/referrers${window.location.search}`} className="font-bold text-grey-darker hover:underline">← All referrers</Link>
|
||||
<Link to={`/${encodeURIComponent(this.props.site.domain)}/referrers${window.location.search}`} className="font-bold text-grey-darker hover:underline">← All referrers</Link>
|
||||
</header>
|
||||
|
||||
<div className="my-4 border-b border-grey-light"></div>
|
||||
|
@ -39,7 +39,7 @@ class Modal extends React.Component {
|
||||
}
|
||||
|
||||
close() {
|
||||
this.props.history.push(`/${this.props.site.domain}${this.props.location.search}`)
|
||||
this.props.history.push(`/${encodeURIComponent(this.props.site.domain)}${this.props.location.search}`)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -16,7 +16,7 @@ class OperatingSystemsModal extends React.Component {
|
||||
componentDidMount() {
|
||||
const query = parseQuery(this.props.location.search, this.props.site)
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/operating-systems`, query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/operating-systems`, query, {limit: 100})
|
||||
.then((res) => this.setState({loading: false, systems: res}))
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class PagesModal extends React.Component {
|
||||
componentDidMount() {
|
||||
const include = this.showBounceRate() ? 'bounce_rate' : null
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/pages`, this.state.query, {limit: 100, include: include})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/pages`, this.state.query, {limit: 100, include: include})
|
||||
.then((res) => this.setState({loading: false, pages: res}))
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,12 @@ class ReferrerDrilldownModal extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
if (this.state.query.filters.goal) {
|
||||
api.get(`/api/stats/${this.props.site.domain}/goal/referrers/${this.props.match.params.referrer}`, this.state.query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/goal/referrers/${this.props.match.params.referrer}`, this.state.query, {limit: 100})
|
||||
.then((res) => this.setState({loading: false, referrers: res.referrers, totalVisitors: res.total_visitors}))
|
||||
} else {
|
||||
const include = this.showBounceRate() ? 'bounce_rate' : null
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/referrers/${this.props.match.params.referrer}`, this.state.query, {limit: 100, include: include})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers/${this.props.match.params.referrer}`, this.state.query, {limit: 100, include: include})
|
||||
.then((res) => this.setState({loading: false, referrers: res.referrers, totalVisitors: res.total_visitors}))
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,7 @@ class ReferrerDrilldownModal extends React.Component {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<header className="modal__header">
|
||||
<Link to={`/${this.props.site.domain}/referrers${window.location.search}`} className="font-bold text-grey-darker hover:underline">← All referrers</Link>
|
||||
<Link to={`/${encodeURIComponent(this.props.site.domain)}/referrers${window.location.search}`} className="font-bold text-grey-darker hover:underline">← All referrers</Link>
|
||||
</header>
|
||||
|
||||
<div className="my-4 border-b border-grey-light"></div>
|
||||
|
@ -17,12 +17,12 @@ class ReferrersModal extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
if (this.state.query.filters.goal) {
|
||||
api.get(`/api/stats/${this.props.site.domain}/goal/referrers`, this.state.query, {limit: 100})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/goal/referrers`, this.state.query, {limit: 100})
|
||||
.then((res) => this.setState({loading: false, referrers: res}))
|
||||
} else {
|
||||
const include = this.showBounceRate() ? 'bounce_rate' : null
|
||||
|
||||
api.get(`/api/stats/${this.props.site.domain}/referrers`, this.state.query, {limit: 100, include: include})
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers`, this.state.query, {limit: 100, include: include})
|
||||
.then((res) => this.setState({loading: false, referrers: res}))
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ class ReferrersModal extends React.Component {
|
||||
return (
|
||||
<tr className="text-sm" key={referrer.name}>
|
||||
<td className="p-2">
|
||||
<Link className="hover:underline truncate" style={{maxWidth: '80%'}} to={`/${this.props.site.domain}/referrers/${referrer.name}${window.location.search}`}>{ referrer.name }</Link>
|
||||
<Link className="hover:underline truncate" style={{maxWidth: '80%'}} to={`/${encodeURIComponent(this.props.site.domain)}/referrers/${referrer.name}${window.location.search}`}>{ referrer.name }</Link>
|
||||
</td>
|
||||
<td className="p-2 w-32 font-medium" align="right">{numberFormatter(referrer.count)}</td>
|
||||
{this.showBounceRate() && <td className="p-2 w-32 font-medium" align="right">{this.formatBounceRate(referrer)}</td> }
|
||||
|
@ -4,7 +4,7 @@ import { Link } from 'react-router-dom'
|
||||
export default function MoreLink({site, endpoint}) {
|
||||
return (
|
||||
<div className="text-center w-full absolute pin-b pin-l p-4">
|
||||
<Link to={`/${site.domain}/${endpoint}${window.location.search}`}className="font-bold text-sm text-grey-dark hover:text-red transition tracking-wide">
|
||||
<Link to={`/${encodeURIComponent(site.domain)}/${endpoint}${window.location.search}`}className="font-bold text-sm text-grey-dark hover:text-red transition tracking-wide">
|
||||
<svg className="feather mr-1"><use xlinkHref="#feather-maximize" /></svg>
|
||||
MORE
|
||||
</Link>
|
||||
|
@ -22,7 +22,7 @@ export default class OperatingSystems extends React.Component {
|
||||
}
|
||||
|
||||
fetchOperatingSystems() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/operating-systems`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/operating-systems`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, systems: res}))
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ export default class Pages extends React.Component {
|
||||
}
|
||||
|
||||
fetchPages() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/pages`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/pages`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, pages: res}))
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,10 @@ export default class Referrers extends React.Component {
|
||||
|
||||
fetchReferrers() {
|
||||
if (this.props.query.filters.goal) {
|
||||
api.get(`/api/stats/${this.props.site.domain}/goal/referrers`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/goal/referrers`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, referrers: res}))
|
||||
} else {
|
||||
api.get(`/api/stats/${this.props.site.domain}/referrers`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/referrers`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, referrers: res}))
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ export default class Referrers extends React.Component {
|
||||
return (
|
||||
<React.Fragment key={referrer.name}>
|
||||
<div className="flex items-center justify-between my-2">
|
||||
<Link className="hover:underline truncate" style={{maxWidth: '80%'}} to={`/${this.props.site.domain}/referrers/${referrer.name}${window.location.search}`}>{ referrer.name }</Link>
|
||||
<Link className="hover:underline truncate" style={{maxWidth: '80%'}} to={`/${encodeURIComponent(this.props.site.domain)}/referrers/${referrer.name}${window.location.search}`}>{ referrer.name }</Link>
|
||||
<span>{numberFormatter(referrer.count)}</span>
|
||||
</div>
|
||||
<Bar count={referrer.count} all={this.state.referrers} color="blue" />
|
||||
|
@ -48,7 +48,7 @@ export default class ScreenSizes extends React.Component {
|
||||
}
|
||||
|
||||
fetchScreenSizes() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/screen-sizes`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/screen-sizes`, this.props.query)
|
||||
.then((res) => this.setState({loading: false, sizes: res}))
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ class LineGraph extends React.Component {
|
||||
}
|
||||
|
||||
downloadLink() {
|
||||
const endpoint = `/${this.props.site.domain}/visitors.csv${api.serializeQuery(this.props.query)}`
|
||||
const endpoint = `/${encodeURIComponent(this.props.site.domain)}/visitors.csv${api.serializeQuery(this.props.query)}`
|
||||
|
||||
return (
|
||||
<a href={endpoint} download>
|
||||
@ -337,7 +337,7 @@ export default class VisitorGraph extends React.Component {
|
||||
}
|
||||
|
||||
fetchGraphData() {
|
||||
api.get(`/api/stats/${this.props.site.domain}/main-graph`, this.props.query)
|
||||
api.get(`/api/stats/${encodeURIComponent(this.props.site.domain)}/main-graph`, this.props.query)
|
||||
.then((res) => {
|
||||
this.setState({loading: false, graphData: res})
|
||||
return res
|
||||
|
@ -2,6 +2,10 @@
|
||||
'use strict';
|
||||
|
||||
try {
|
||||
const CONFIG = {
|
||||
domain: window.location.hostname
|
||||
}
|
||||
|
||||
function setCookie(name,value) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (3*365*24*60*60*1000)); // 3 YEARS
|
||||
@ -76,6 +80,7 @@
|
||||
var payload = getUserData()
|
||||
payload.name = eventName
|
||||
payload.url = getUrl()
|
||||
payload.domain = CONFIG['domain']
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', plausibleHost + '/api/event', true);
|
||||
@ -113,10 +118,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function configure(key, val) {
|
||||
CONFIG[key] = val
|
||||
}
|
||||
|
||||
const functions = {
|
||||
page: page,
|
||||
trigger: trigger,
|
||||
trackPushState: trackPushState
|
||||
trackPushState: trackPushState,
|
||||
configure: configure
|
||||
}
|
||||
|
||||
const queue = window.plausible.q || []
|
||||
|
@ -33,8 +33,8 @@ defmodule Mix.Tasks.SendEmailReports do
|
||||
query = Stats.Query.from(site.timezone, %{"period" => "7d"})
|
||||
|
||||
for email <- site.weekly_report.recipients do
|
||||
Logger.info("Sending weekly report for #{site.domain} to #{email}")
|
||||
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{site.domain}/weekly-report/unsubscribe?email=#{email}"
|
||||
Logger.info("Sending weekly report for #{URI.encode_www_form(site.domain)} to #{email}")
|
||||
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{URI.encode_www_form(site.domain)}/weekly-report/unsubscribe?email=#{email}"
|
||||
send_report(email, site, "Weekly", unsubscribe_link, query)
|
||||
end
|
||||
|
||||
@ -59,7 +59,7 @@ defmodule Mix.Tasks.SendEmailReports do
|
||||
|
||||
for email <- site.monthly_report.recipients do
|
||||
Logger.info("Sending monthly report for #{site.domain} to #{email}")
|
||||
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{site.domain}/monthly-report/unsubscribe?email=#{email}"
|
||||
unsubscribe_link = PlausibleWeb.Endpoint.url() <> "/sites/#{URI.encode_www_form(site.domain)}/monthly-report/unsubscribe?email=#{email}"
|
||||
send_report(email, site, Timex.format!(last_month, "{Mfull}"), unsubscribe_link, query)
|
||||
end
|
||||
|
||||
@ -115,11 +115,11 @@ defmodule Mix.Tasks.SendEmailReports do
|
||||
end
|
||||
|
||||
defp view_link(site, %Plausible.Stats.Query{period: "7d"}) do
|
||||
PlausibleWeb.Endpoint.url() <> "/#{site.domain}?period=7d"
|
||||
PlausibleWeb.Endpoint.url() <> "/#{URI.encode_www_form(site.domain)}?period=7d"
|
||||
end
|
||||
|
||||
defp view_link(site, %Plausible.Stats.Query{period: "month", date_range: range}) do
|
||||
month = Timex.format!(range.first, "{ISOdate}")
|
||||
PlausibleWeb.Endpoint.url() <> "/#{site.domain}?period=month&date=#{month}"
|
||||
PlausibleWeb.Endpoint.url() <> "/#{URI.encode_www_form(site.domain)}?period=month&date=#{month}"
|
||||
end
|
||||
end
|
||||
|
@ -44,42 +44,6 @@ defmodule Mix.Tasks.SendTrialNotifications do
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
#two_weeks_left = from(
|
||||
# u in base_query,
|
||||
# where: type(u.inserted_at, :date) == fragment("now()::date - '14 days'::interval")
|
||||
#)
|
||||
|
||||
#tomorrow = from(
|
||||
# u in base_query,
|
||||
# where: type(u.inserted_at, :date) == fragment("now()::date - '29 days'::interval")
|
||||
#)
|
||||
|
||||
#today = from(
|
||||
# u in base_query,
|
||||
# where: type(u.inserted_at, :date) == fragment("now()::date - '30 days'::interval")
|
||||
#)
|
||||
|
||||
#yesterday = from(
|
||||
# u in base_query,
|
||||
# where: type(u.inserted_at, :date) == fragment("now()::date - '31 days'::interval")
|
||||
#)
|
||||
|
||||
#for user <- Repo.all(two_weeks_left) do
|
||||
# if Plausible.Auth.user_completed_setup?(user), do: send_two_week_reminder(args, user)
|
||||
#end
|
||||
|
||||
#for user <- Repo.all(tomorrow) do
|
||||
# if Plausible.Auth.user_completed_setup?(user), do: send_tomorrow_reminder(args, user)
|
||||
#end
|
||||
|
||||
#for user <- Repo.all(today) do
|
||||
# if Plausible.Auth.user_completed_setup?(user), do: send_today_reminder(args, user)
|
||||
#end
|
||||
|
||||
#for user <- Repo.all(yesterday) do
|
||||
# if Plausible.Auth.user_completed_setup?(user), do: send_over_reminder(args, user)
|
||||
#end
|
||||
end
|
||||
|
||||
defp send_two_week_reminder(["--dry-run"], user) do
|
||||
|
@ -17,7 +17,7 @@ defmodule Plausible.Auth do
|
||||
from(
|
||||
e in Plausible.Event,
|
||||
join: s in Plausible.Site,
|
||||
on: s.domain == e.hostname,
|
||||
on: s.domain == e.domain,
|
||||
join: sm in Plausible.Site.Membership,
|
||||
on: sm.site_id == s.id,
|
||||
join: u in Plausible.Auth.User,
|
||||
|
@ -101,7 +101,7 @@ defmodule Plausible.Billing do
|
||||
defp site_usage(site) do
|
||||
Repo.aggregate(from(
|
||||
e in Plausible.Event,
|
||||
where: e.hostname == ^site.domain,
|
||||
where: e.domain == ^site.domain,
|
||||
where: e.timestamp >= fragment("now() - '30 days'::interval")
|
||||
), :count, :id)
|
||||
end
|
||||
|
@ -4,6 +4,7 @@ defmodule Plausible.Event do
|
||||
|
||||
schema "events" do
|
||||
field :name, :string
|
||||
field :domain, :string
|
||||
field :hostname, :string
|
||||
field :pathname, :string
|
||||
field :new_visitor, :boolean
|
||||
@ -21,7 +22,7 @@ defmodule Plausible.Event do
|
||||
|
||||
def changeset(pageview, attrs) do
|
||||
pageview
|
||||
|> cast(attrs, [:name, :hostname, :pathname, :referrer, :new_visitor, :user_id, :operating_system, :browser, :referrer_source, :country_code, :screen_size])
|
||||
|> validate_required([:name, :hostname, :pathname, :new_visitor, :user_id])
|
||||
|> cast(attrs, [:name, :domain, :hostname, :pathname, :referrer, :new_visitor, :user_id, :operating_system, :browser, :referrer_source, :country_code, :screen_size])
|
||||
|> validate_required([:name, :domain, :hostname, :pathname, :new_visitor, :user_id])
|
||||
end
|
||||
end
|
||||
|
@ -48,6 +48,7 @@ defmodule Plausible.Ingest.Session do
|
||||
|
||||
Plausible.Session.changeset(%Plausible.Session{}, %{
|
||||
hostname: first_event.hostname,
|
||||
domain: first_event.domain,
|
||||
user_id: first_event.user_id,
|
||||
new_visitor: first_event.new_visitor,
|
||||
entry_page: first_event.pathname,
|
||||
|
@ -4,6 +4,7 @@ defmodule Plausible.Session do
|
||||
|
||||
schema "sessions" do
|
||||
field :hostname, :string
|
||||
field :domain, :string
|
||||
field :new_visitor, :boolean
|
||||
field :user_id, :binary_id
|
||||
|
||||
@ -25,7 +26,7 @@ defmodule Plausible.Session do
|
||||
|
||||
def changeset(session, attrs) do
|
||||
session
|
||||
|> cast(attrs, [:hostname, :entry_page, :exit_page, :referrer, :new_visitor, :user_id, :start, :length, :is_bounce, :operating_system, :browser, :referrer_source, :country_code, :screen_size])
|
||||
|> validate_required([:hostname, :new_visitor, :user_id, :is_bounce, :start])
|
||||
|> cast(attrs, [:hostname, :domain, :entry_page, :exit_page, :referrer, :new_visitor, :user_id, :start, :length, :is_bounce, :operating_system, :browser, :referrer_source, :country_code, :screen_size])
|
||||
|> validate_required([:hostname, :domain, :new_visitor, :user_id, :is_bounce, :start])
|
||||
end
|
||||
end
|
||||
|
@ -14,7 +14,7 @@ defmodule Plausible.Sites do
|
||||
def has_pageviews?(site) do
|
||||
Repo.exists?(
|
||||
from e in Plausible.Event,
|
||||
where: e.hostname == ^site.domain
|
||||
where: e.domain == ^site.domain
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -126,7 +126,7 @@ defmodule Plausible.Stats do
|
||||
{first_datetime, last_datetime} = date_range_utc_boundaries(query.date_range, site.timezone)
|
||||
|
||||
sessions_query = from(s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime
|
||||
)
|
||||
@ -143,7 +143,7 @@ defmodule Plausible.Stats do
|
||||
{first_datetime, last_datetime} = date_range_utc_boundaries(query.date_range, site.timezone)
|
||||
|
||||
Repo.one(from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
select: coalesce(avg(s.length), 0)
|
||||
) |> Decimal.round |> Decimal.to_integer
|
||||
@ -199,7 +199,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
total_sessions_by_referrer = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.referrer_source in ^referrers,
|
||||
@ -209,7 +209,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
bounced_sessions_by_referrer = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.is_bounce,
|
||||
@ -300,7 +300,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
total_sessions_by_url = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.referrer in ^referring_urls,
|
||||
@ -310,7 +310,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
bounced_sessions_by_url = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.is_bounce,
|
||||
@ -355,7 +355,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
total_sessions_by_url = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.entry_page in ^page_urls,
|
||||
@ -365,7 +365,7 @@ defmodule Plausible.Stats do
|
||||
|
||||
bounced_sessions_by_url = Repo.all(
|
||||
from s in Plausible.Session,
|
||||
where: s.hostname == ^site.domain,
|
||||
where: s.domain == ^site.domain,
|
||||
where: s.new_visitor,
|
||||
where: s.start >= ^first_datetime and s.start < ^last_datetime,
|
||||
where: s.is_bounce,
|
||||
@ -453,7 +453,7 @@ defmodule Plausible.Stats do
|
||||
Repo.one(
|
||||
from e in Plausible.Event,
|
||||
where: e.timestamp >= fragment("(now() at time zone 'utc') - '5 minutes'::interval"),
|
||||
where: e.hostname == ^site.domain,
|
||||
where: e.domain == ^site.domain,
|
||||
select: count(e.user_id, :distinct)
|
||||
)
|
||||
end
|
||||
@ -513,7 +513,7 @@ defmodule Plausible.Stats do
|
||||
{goal_event, path} = event_name_for_goal(query)
|
||||
|
||||
q = from(e in Plausible.Event,
|
||||
where: e.hostname == ^site.domain,
|
||||
where: e.domain == ^site.domain,
|
||||
where: e.timestamp >= ^first_datetime and e.timestamp < ^last_datetime
|
||||
)
|
||||
|
||||
|
@ -50,6 +50,7 @@ defmodule PlausibleWeb.Api.ExternalController do
|
||||
event_attrs = %{
|
||||
name: params["name"],
|
||||
hostname: strip_www(uri.host),
|
||||
domain: params["domain"] || strip_www(uri.host),
|
||||
pathname: uri.path,
|
||||
new_visitor: params["new_visitor"],
|
||||
country_code: country_code,
|
||||
|
@ -5,7 +5,7 @@ defmodule PlausibleWeb.Api.InternalController do
|
||||
def domain_status(conn, %{"domain" => domain}) do
|
||||
has_pageviews = Repo.exists?(
|
||||
from e in Plausible.Event,
|
||||
where: e.hostname == ^domain
|
||||
where: e.domain == ^domain
|
||||
)
|
||||
|
||||
if has_pageviews do
|
||||
|
@ -208,6 +208,6 @@ defmodule PlausibleWeb.AuthController do
|
||||
|
||||
site = Repo.get(Plausible.Site, site_id)
|
||||
|
||||
redirect(conn, to: "/#{site.domain}/settings#google-auth")
|
||||
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings#google-auth")
|
||||
end
|
||||
end
|
||||
|
@ -19,7 +19,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
Plausible.Slack.notify("#{user.name} created #{site.domain}")
|
||||
conn
|
||||
|> put_session(site.domain <> "_offer_email_report", true)
|
||||
|> redirect(to: "/#{site.domain}/snippet")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/snippet")
|
||||
{:error, :site, changeset, _} ->
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
@ -52,7 +52,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
{:ok, _} ->
|
||||
conn
|
||||
|> put_flash(:success, "Goal created succesfully")
|
||||
|> redirect(to: "/#{website}/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
||||
{:error, :goal, changeset, _} ->
|
||||
conn
|
||||
|> assign(:skip_plausible_tracking, true)
|
||||
@ -69,7 +69,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Goal deleted succesfully")
|
||||
|> redirect(to: "/#{website}/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(website)}/settings")
|
||||
end
|
||||
|
||||
def settings(conn, %{"website" => website}) do
|
||||
@ -107,7 +107,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Google integration saved succesfully")
|
||||
|> redirect(to: "/#{site.domain}/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#google-auth")
|
||||
end
|
||||
|
||||
def update_settings(conn, %{"website" => website, "site" => site_params}) do
|
||||
@ -122,7 +122,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
conn
|
||||
|> put_session(site_session_key, nil)
|
||||
|> put_flash(:success, "Site settings saved succesfully")
|
||||
|> redirect(to: "/#{site.domain}/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
||||
{:error, changeset} ->
|
||||
render("settings.html", site: site, changeset: changeset)
|
||||
end
|
||||
@ -134,7 +134,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|> Repo.preload(:google_auth)
|
||||
|
||||
Repo.delete_all(from sm in "site_memberships", where: sm.site_id == ^site.id)
|
||||
Repo.delete_all(from e in "events", where: e.hostname == ^site.domain)
|
||||
Repo.delete_all(from e in "events", where: e.domain == ^site.domain)
|
||||
|
||||
if site.google_auth do
|
||||
Repo.delete!(site.google_auth)
|
||||
@ -153,7 +153,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Congrats! Stats for #{site.domain} are now public.")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
||||
end
|
||||
|
||||
def make_private(conn, %{"website" => website}) do
|
||||
@ -163,7 +163,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Stats for #{site.domain} are now private.")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
||||
end
|
||||
|
||||
def enable_weekly_report(conn, %{"website" => website}) do
|
||||
@ -177,7 +177,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Success! You will receive an email report every Monday going forward")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def disable_weekly_report(conn, %{"website" => website}) do
|
||||
@ -186,7 +186,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Success! You will not receive weekly email reports going forward")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def add_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||
@ -198,7 +198,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Succesfully added #{recipient} as a recipient for the weekly report")
|
||||
|> redirect(to: "/#{site.domain}/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def remove_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||
@ -210,7 +210,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Succesfully removed #{recipient} as a recipient for the weekly report")
|
||||
|> redirect(to: "/#{site.domain}/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def enable_monthly_report(conn, %{"website" => website}) do
|
||||
@ -224,7 +224,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Success! You will receive an email report every month going forward")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def disable_monthly_report(conn, %{"website" => website}) do
|
||||
@ -233,7 +233,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Success! You will not receive monthly email reports going forward")
|
||||
|> redirect(to: "/" <> site.domain <> "/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def add_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||
@ -245,7 +245,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Succesfully added #{recipient} as a recipient for the monthly report")
|
||||
|> redirect(to: "/#{site.domain}/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def remove_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||
@ -257,7 +257,7 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
conn
|
||||
|> put_flash(:success, "Succesfully removed #{recipient} as a recipient for the monthly report")
|
||||
|> redirect(to: "/#{site.domain}/settings#email-reports")
|
||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
||||
end
|
||||
|
||||
def new_shared_link(conn, %{"website" => website}) do
|
||||
@ -276,17 +276,18 @@ defmodule PlausibleWeb.SiteController do
|
||||
|
||||
case Repo.insert(changes) do
|
||||
{:ok, _created} ->
|
||||
redirect(conn, to: "/#{site.domain}/settings#visibility")
|
||||
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings#visibility")
|
||||
{:error, changeset} ->
|
||||
render(conn, "new_shared_link.html", site: site, changeset: changeset, layout: {PlausibleWeb.LayoutView, "focus.html"})
|
||||
end
|
||||
end
|
||||
|
||||
def delete_shared_link(conn, %{"website" => website, "slug" => slug}) do
|
||||
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||
Repo.get_by(Plausible.Site.SharedLink, slug: slug)
|
||||
|> Repo.delete!
|
||||
|
||||
redirect(conn, to: "/#{website}/settings#visibility")
|
||||
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings#visibility")
|
||||
end
|
||||
|
||||
defp insert_site(user_id, params) do
|
||||
|
@ -7,10 +7,10 @@
|
||||
<div class="overflow-hidden bg-white rounded max-w-md w-full shadow-md leading-normal">
|
||||
<%= for site <- @sites do %>
|
||||
<div class="w-full relative">
|
||||
<a href="/<%= site.domain %>" class="block hover:bg-grey-lighter group p-4 border-b no-underline flex justify-between transition">
|
||||
<a href="/<%= URI.encode_www_form(site.domain) %>" class="block hover:bg-grey-lighter group p-4 border-b no-underline flex justify-between transition">
|
||||
<p class="w-full font-bold text-lg mb-1 text-grey-darkest"><%= site.domain %></p>
|
||||
</a>
|
||||
<%= link(to: "/#{site.domain}/settings", class: "flex absolute hover:bg-grey-lighter transition rounded py-3 px-5", style: "top: 6px; right: 6px;") do %>
|
||||
<%= link(to: "/#{URI.encode_www_form(site.domain)}/settings", class: "flex absolute hover:bg-grey-lighter transition rounded py-3 px-5", style: "top: 6px; right: 6px;") do %>
|
||||
<div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<%= form_for @changeset, "/#{@site.domain}/goals", [class: "max-w-sm w-full mx-auto bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %>
|
||||
<%= form_for @changeset, "/#{URI.encode_www_form(@site.domain)}/goals", [class: "max-w-sm w-full mx-auto bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %>
|
||||
<h2>Add goal for <%= @site.domain %></h2>
|
||||
<div class="mt-6 text-sm font-bold">Goal trigger</div>
|
||||
<div class="my-3 w-full flex rounded border border-grey-light">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<%= form_for @changeset, "/sites/#{@site.domain}/shared-links", [class: "max-w-sm w-full mx-auto bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %>
|
||||
<%= form_for @changeset, "/sites/#{URI.encode_www_form(@site.domain)}/shared-links", [class: "max-w-sm w-full mx-auto bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %>
|
||||
<h2>New shared link</h2>
|
||||
<div class="my-6">
|
||||
Add a password or leave it blank so anyone with the link can see the stats.
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="pt-24"></div>
|
||||
<div class="max-w-md mx-auto flex justify-between">
|
||||
<a href="/<%= @site.domain %>"><h1>Settings for <%= @site.domain %></h1></a>
|
||||
<a href="/<%= URI.encode_www_form(@site.domain) %>"><h1>Settings for <%= @site.domain %></h1></a>
|
||||
</div>
|
||||
<div class="max-w-md mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-lightest px-8 pt-6 pb-8 mt-10">
|
||||
<div class="flex items-center justify-between">
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<div class="my-4 border-b border-grey-light"></div>
|
||||
|
||||
<%= form_for @changeset, "/#{@site.domain}/settings", [class: "max-w-xs"], fn f -> %>
|
||||
<%= form_for @changeset, "/#{URI.encode_www_form(@site.domain)}/settings", [class: "max-w-xs"], fn f -> %>
|
||||
<div class="my-4">
|
||||
<%= label f, :domain, class: "block text-grey-darker text-sm font-bold mb-2" %>
|
||||
<%= text_input f, :domain, class: "transition bg-grey-lighter appearance-none border border-transparent rounded w-full p-2 text-grey-darker leading-normal appearance-none focus:outline-none focus:border-grey-light ", disabled: "disabled" %>
|
||||
@ -37,18 +37,18 @@
|
||||
<%= if @site.public do %>
|
||||
Stats for <%= @site.domain %> are currently <b>public</b>. Anyone with the following link can view the stats:
|
||||
<div class="relative text-sm mt-4">
|
||||
<input type="text" id="public-link" value="https://plausible.io/<%= @site.domain %>" class="transition bg-grey-lighter appearance-none border border-transparent rounded w-full p-2 pr-16 text-grey-darker appearance-none focus:outline-none focus:border-grey-light" />
|
||||
<input type="text" id="public-link" value="https://plausible.io/<%= URI.encode_www_form(@site.domain) %>" class="transition bg-grey-lighter appearance-none border border-transparent rounded w-full p-2 pr-16 text-grey-darker appearance-none focus:outline-none focus:border-grey-light" />
|
||||
<a onclick="var input = document.getElementById('public-link'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="absolute pin-r text-indigo-darker font-bold p-2">
|
||||
<svg class="feather-sm"><use xlink:href="#feather-copy" /></svg>
|
||||
</a>
|
||||
</div>
|
||||
<%= button("Make stats private", to: "/sites/#{@site.domain}/make-private", method: "POST", class: "button mt-8") %>
|
||||
<%= button("Make stats private", to: "/sites/#{URI.encode_www_form(@site.domain)}/make-private", method: "POST", class: "button mt-8") %>
|
||||
<% else %>
|
||||
<div class="text-grey-darker">
|
||||
Stats for <%= @site.domain %> are currently <b>private</b>. You are the only person who can see them.
|
||||
If you choose to make your stats public, anyone with the link will be able to view them.
|
||||
</div>
|
||||
<%= button("Make stats public", to: "/sites/#{@site.domain}/make-public", method: "POST", class: "button mt-8") %>
|
||||
<%= button("Make stats public", to: "/sites/#{URI.encode_www_form(@site.domain)}/make-public", method: "POST", class: "button mt-8") %>
|
||||
<% end %>
|
||||
|
||||
<div class="mt-16">
|
||||
@ -67,14 +67,14 @@
|
||||
<button onclick="var input = document.getElementById('<%= link.slug %>'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="py-2 px-4 bg-grey-lighter text-indigo-darker rounded-none border-r border-grey-light">
|
||||
<svg class="feather-sm"><use xlink:href="#feather-copy" /></svg>
|
||||
</button>
|
||||
<%= button(to: "/sites/#{@site.domain}/shared-links/#{link.slug}", method: :delete, class: "py-2 px-4 bg-grey-lighter text-red-dark rounded-l-none", data: [confirm: "Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."]) do %>
|
||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/#{link.slug}", method: :delete, class: "py-2 px-4 bg-grey-lighter text-red-dark rounded-l-none", data: [confirm: "Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."]) do %>
|
||||
<svg class="feather-sm"><use xlink:href="#feather-trash-2" /></svg>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= link("+ New link", to: "/sites/#{@site.domain}/shared-links/new", class: "button mt-4") %>
|
||||
<%= link("+ New link", to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/new", class: "button mt-4") %>
|
||||
</div>
|
||||
|
||||
<div class="max-w-md mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-lightest px-8 pt-6 pb-8 mt-10">
|
||||
@ -85,7 +85,7 @@
|
||||
<%= for goal <- @goals do %>
|
||||
<div class="border-b border-grey-light py-3 flex justify-between">
|
||||
<small class="font-bold"><%= goal_name(goal) %></small>
|
||||
<%= button("❌", to: "/#{@site.domain}/goals/#{goal.id}", method: :delete, class: "text-sm", data: [confirm: "Are you sure you want to remove goal #{goal_name(goal)}? This will just affect the UI, all of your analytics data will stay intact."]) %>
|
||||
<%= button("❌", to: "/#{URI.encode_www_form(@site.domain)}/goals/#{goal.id}", method: :delete, class: "text-sm", data: [confirm: "Are you sure you want to remove goal #{goal_name(goal)}? This will just affect the UI, all of your analytics data will stay intact."]) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
@ -93,7 +93,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= link("+ Add goal", to: "/#{@site.domain}/goals/new", class: "button mt-6") %>
|
||||
<%= link("+ Add goal", to: "/#{URI.encode_www_form(@site.domain)}/goals/new", class: "button mt-6") %>
|
||||
</div>
|
||||
|
||||
<div class="max-w-md mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-lightest px-8 pt-6 pb-8 mt-10" id="google-auth">
|
||||
@ -120,7 +120,7 @@
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<%= form_for Plausible.Site.GoogleAuth.changeset(@site.google_auth), "/#{@site.domain}/settings/google", [class: "max-w-xs"], fn f -> %>
|
||||
<%= form_for Plausible.Site.GoogleAuth.changeset(@site.google_auth), "/#{URI.encode_www_form(@site.domain)}/settings/google", [class: "max-w-xs"], fn f -> %>
|
||||
<div class="my-6">
|
||||
<div class="inline-block relative w-full">
|
||||
<%= select f, :property, @search_console_domains, prompt: "(Choose property)", class: "block appearance-none w-full bg-grey-lighter text-grey-darker cursor-pointer hover:border-grey p-2 pr-8 rounded leading-normal focus:outline-none" %>
|
||||
@ -148,11 +148,11 @@
|
||||
|
||||
<div class="my-8 flex items-center">
|
||||
<%= if @weekly_report do %>
|
||||
<%= button(to: "/sites/#{@site.domain}/weekly-report/disable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 bg-green justify-end") do %>
|
||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/disable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 bg-green justify-end") do %>
|
||||
<span class="rounded-full border w-4 h-4 border-grey shadow-inner bg-white shadow"></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= button(to: "/sites/#{@site.domain}/weekly-report/enable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 justify-start") do %>
|
||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/enable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 justify-start") do %>
|
||||
<span class="rounded-full border w-4 h-4 border-grey shadow-inner bg-white shadow"></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@ -164,10 +164,10 @@
|
||||
<%= for recipient <- @weekly_report.recipients do %>
|
||||
<div class="p-3 flex justify-between bg-grey-lighter rounded my-2 max-w-sm">
|
||||
<span><svg class="feather mr-1" style="transform: translateY(0.05em)"><use xlink:href="#feather-mail" /></svg><%= recipient %></span>
|
||||
<%= button("❌", to: "/sites/#{@site.domain}/weekly-report/recipients/#{recipient}", method: :delete) %>
|
||||
<%= button("❌", to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients/#{recipient}", method: :delete) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= form_for @conn, "/sites/#{@site.domain}/weekly-report/recipients", fn f -> %>
|
||||
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients", fn f -> %>
|
||||
<div class="flex justify-between my-2 max-w-sm">
|
||||
<%= email_input f, :recipient, class: "transition bg-grey-lighter appearance-none border border-transparent rounded w-full p-2 text-grey-darker leading-normal appearance-none focus:outline-none focus:border-grey-light", style: "flex-grow: 2", placeholder: "recipient@example.com" %>
|
||||
<%= submit "Add recipient", class: "button rounded-l-none whitespace-no-wrap" %>
|
||||
@ -178,11 +178,11 @@
|
||||
<div class="my-8 border-b border-grey-light"></div>
|
||||
<div class="my-8 flex items-center">
|
||||
<%= if @monthly_report do %>
|
||||
<%= button(to: "/sites/#{@site.domain}/monthly-report/disable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 bg-green justify-end") do %>
|
||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/disable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 bg-green justify-end") do %>
|
||||
<span class="rounded-full border w-4 h-4 border-grey shadow-inner bg-white shadow"></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= button(to: "/sites/#{@site.domain}/monthly-report/enable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 justify-start") do %>
|
||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/enable", method: :post, class: "border rounded-full border-grey flex items-center cursor-pointer w-8 justify-start") do %>
|
||||
<span class="rounded-full border w-4 h-4 border-grey shadow-inner bg-white shadow"></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@ -194,10 +194,10 @@
|
||||
<%= for recipient <- @monthly_report.recipients do %>
|
||||
<div class="p-3 flex justify-between bg-grey-lighter rounded my-2 max-w-sm">
|
||||
<span><svg class="feather mr-1" style="transform: translateY(0.05em)"><use xlink:href="#feather-mail" /></svg><%= recipient %></span>
|
||||
<%= button("❌", to: "/sites/#{@site.domain}/monthly-report/recipients/#{recipient}", method: :delete) %>
|
||||
<%= button("❌", to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients/#{recipient}", method: :delete) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= form_for @conn, "/sites/#{@site.domain}/monthly-report/recipients", fn f -> %>
|
||||
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients", fn f -> %>
|
||||
<div class="flex justify-between my-2 max-w-sm">
|
||||
<%= email_input f, :recipient, class: "transition bg-grey-lighter appearance-none border border-transparent rounded w-full p-2 text-grey-darker leading-normal appearance-none focus:outline-none focus:border-grey-light", style: "flex-grow: 2", placeholder: "recipient@example.com" %>
|
||||
<%= submit "Add recipient", class: "button rounded-l-none whitespace-no-wrap" %>
|
||||
@ -234,5 +234,5 @@
|
||||
<div class="my-4 border-b border-grey-light"></div>
|
||||
|
||||
<p class="text-lg">Deleting the site removes all stats you've collected</p>
|
||||
<%= link "Delete #{@site.domain}", to: "/#{@site.domain}", method: :delete, class: "button bg-red-dark mt-4", data: [confirm: "Deleting the site data cannot be reversed. Are you sure?"] %>
|
||||
<%= link "Delete #{@site.domain}", to: "/#{URI.encode_www_form(@site.domain)}", method: :delete, class: "button bg-red-dark mt-4", data: [confirm: "Deleting the site data cannot be reversed. Are you sure?"] %>
|
||||
</div>
|
||||
|
@ -15,5 +15,5 @@
|
||||
<%= link("Read the docs", class: "text-indigo hover:underline", to: "https://docs.plausible.io/single-page-application-support", target: "_blank") %>
|
||||
</div>
|
||||
</div>
|
||||
<%= link("Start collecting data →", class: "button mt-4 w-full", to: "/#{@site.domain}") %>
|
||||
<%= link("Start collecting data →", class: "button mt-4 w-full", to: "/#{URI.encode_www_form(@site.domain)}") %>
|
||||
<% end %>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="container pb-32" data-site-domain="<%= @site.domain %>">
|
||||
<%= if @offer_email_report do %>
|
||||
<div class="text-center bg-blue-lighter text-blue-darkest text-sm font-bold px-4 w-full rounded transition" style="top: 91px" role="alert">
|
||||
<%= link("Click here to enable weekly email reports →", to: "/#{@site.domain}/settings#email-reports", class: "py-2 block") %>
|
||||
<%= link("Click here to enable weekly email reports →", to: "/#{URI.encode_www_form(@site.domain)}/settings#email-reports", class: "py-2 block") %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="pt-12"></div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/3.0.0/fetch.min.js" integrity="sha256-E1M+0f/hvoNVoV8K5RSn1gwe4EFwlvORnOrFzghX0wM=" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
function updateStatus() {
|
||||
fetch("/api/<%= @site.domain %>/status")
|
||||
fetch("/api/<%= URI.encode_www_form(@site.domain) %>/status")
|
||||
.then(function(res) { return res.json() })
|
||||
.then(function(status) {
|
||||
if (status === "READY") {
|
||||
@ -20,7 +20,7 @@
|
||||
<div class="my-4">
|
||||
<div class="pulsating-circle"></div>
|
||||
<p class="text-grey-dark text-sm absolute pin-l pin-b mb-6 w-full text-center leading-normal">
|
||||
Need to see the snippet again? <%= link("Click here", to: "/#{@site.domain}/snippet")%><br />
|
||||
Need to see the snippet again? <%= link("Click here", to: "/#{URI.encode_www_form(@site.domain)}/snippet")%><br />
|
||||
Not working? Contact <a href="mailto:uku@plausible.io">uku@plausible.io</a> to get set up
|
||||
</p>
|
||||
</div>
|
||||
|
@ -0,0 +1,37 @@
|
||||
defmodule Plausible.Repo.Migrations.AddSiteIdToEvents do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:events) do
|
||||
add :site_id, :text
|
||||
end
|
||||
|
||||
alter table(:sessions) do
|
||||
add :site_id, :text
|
||||
end
|
||||
|
||||
execute "UPDATE events set site_id=hostname"
|
||||
execute "UPDATE sessions set site_id=hostname"
|
||||
|
||||
alter table(:events) do
|
||||
modify :site_id, :text, null: false
|
||||
end
|
||||
|
||||
alter table(:sessions) do
|
||||
modify :site_id, :text, null: false
|
||||
end
|
||||
|
||||
create index(:events, :site_id)
|
||||
create index(:sessions, :site_id)
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:events) do
|
||||
remove :site_id
|
||||
end
|
||||
|
||||
alter table(:sessions) do
|
||||
remove :site_id
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,8 @@
|
||||
defmodule Plausible.Repo.Migrations.RenameSiteIdToDomain do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
rename table(:events), :site_id, to: :domain
|
||||
rename table(:sessions), :site_id, to: :domain
|
||||
end
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
defmodule Plausible.Repo.Migrations.DropEventsHostnameIndex do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
drop index("pageviews", :hostname)
|
||||
end
|
||||
end
|
@ -17,7 +17,7 @@ defmodule Mix.Tasks.SendFeedbackEmailsTest do
|
||||
test "sends an email if the user is more than 30 days old and logged on in the last week" do
|
||||
user = insert(:user, inserted_at: days_ago(31), last_seen: days_ago(1))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
SendFeedbackEmails.execute()
|
||||
|
||||
@ -27,7 +27,7 @@ defmodule Mix.Tasks.SendFeedbackEmailsTest do
|
||||
test "sends the email only once" do
|
||||
user = insert(:user, inserted_at: days_ago(31), last_seen: days_ago(1))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
SendFeedbackEmails.execute()
|
||||
assert_email_delivered_with(subject: "Plausible feedback")
|
||||
@ -39,7 +39,7 @@ defmodule Mix.Tasks.SendFeedbackEmailsTest do
|
||||
test "does not send if user has not logged in recently" do
|
||||
user = insert(:user, inserted_at: days_ago(31), last_seen: days_ago(15))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
SendFeedbackEmails.execute()
|
||||
|
||||
@ -49,7 +49,7 @@ defmodule Mix.Tasks.SendFeedbackEmailsTest do
|
||||
test "does not send if user is less than a month old" do
|
||||
user = insert(:user, inserted_at: days_ago(15), last_seen: days_ago(1))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
SendFeedbackEmails.execute()
|
||||
|
||||
|
@ -66,7 +66,7 @@ defmodule Mix.Tasks.SendIntroEmailsTest do
|
||||
test "sends a welcome email 6 hours after signup if the user has created a site and has received a pageview" do
|
||||
user = insert(:user, inserted_at: hours_ago(6))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendIntroEmails.execute()
|
||||
|
||||
@ -79,7 +79,7 @@ defmodule Mix.Tasks.SendIntroEmailsTest do
|
||||
test "sends a welcome email 23 hours after signup" do
|
||||
user = insert(:user, inserted_at: hours_ago(23))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendIntroEmails.execute()
|
||||
|
||||
@ -92,7 +92,7 @@ defmodule Mix.Tasks.SendIntroEmailsTest do
|
||||
test "does not send a welcome email 24 hours after signup" do
|
||||
user = insert(:user, inserted_at: hours_ago(24))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendIntroEmails.execute()
|
||||
|
||||
@ -106,7 +106,7 @@ defmodule Mix.Tasks.SendIntroEmailsTest do
|
||||
Mix.Tasks.SendIntroEmails.execute()
|
||||
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendIntroEmails.execute()
|
||||
|
||||
|
@ -17,7 +17,7 @@ defmodule Mix.Tasks.SendTrialNotificationsTest do
|
||||
test "sends a reminder 14 days before trial ends (16 days after user signed up)" do
|
||||
user = insert(:user, inserted_at: Timex.now |> Timex.shift(days: -16))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendTrialNotifications.execute()
|
||||
|
||||
@ -27,7 +27,7 @@ defmodule Mix.Tasks.SendTrialNotificationsTest do
|
||||
test "sends an upgrade email the day before the trial ends" do
|
||||
user = insert(:user, inserted_at: Timex.now |> Timex.shift(days: -29))
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
Mix.Tasks.SendTrialNotifications.execute()
|
||||
|
||||
@ -37,10 +37,10 @@ defmodule Mix.Tasks.SendTrialNotificationsTest do
|
||||
test "does not send a notification if user has a subscription" do
|
||||
user1 = insert(:user, inserted_at: Timex.now |> Timex.shift(days: -14))
|
||||
site1 = insert(:site, members: [user1])
|
||||
insert(:pageview, hostname: site1.domain)
|
||||
insert(:pageview, domain: site1.domain)
|
||||
user2 = insert(:user, inserted_at: Timex.now |> Timex.shift(days: -29))
|
||||
site2 = insert(:site, members: [user2])
|
||||
insert(:pageview, hostname: site2.domain)
|
||||
insert(:pageview, domain: site2.domain)
|
||||
|
||||
insert(:subscription, user: user1)
|
||||
insert(:subscription, user: user2)
|
||||
|
@ -13,7 +13,7 @@ defmodule Plausible.AuthTest do
|
||||
test "is true if user does have events" do
|
||||
user = insert(:user)
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
assert Auth.user_completed_setup?(user)
|
||||
end
|
||||
|
@ -12,8 +12,8 @@ defmodule Plausible.BillingTest do
|
||||
test "counts the total number of events" do
|
||||
user = insert(:user)
|
||||
site = insert(:site, members: [user])
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
assert Billing.usage(user) == 2
|
||||
end
|
||||
|
@ -5,7 +5,7 @@ defmodule Plausible.SitesTest do
|
||||
describe "has_pageviews?" do
|
||||
test "is true if site has pageviews" do
|
||||
site = insert(:site)
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
assert Sites.has_pageviews?(site)
|
||||
end
|
||||
|
@ -34,11 +34,33 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
|
||||
|
||||
assert response(conn, 202) == ""
|
||||
assert pageview.hostname == "gigride.live"
|
||||
assert pageview.domain == "gigride.live"
|
||||
assert pageview.pathname == "/"
|
||||
assert pageview.new_visitor == true
|
||||
assert pageview.country_code == @country_code
|
||||
end
|
||||
|
||||
test "can specify the domain", %{conn: conn} do
|
||||
params = %{
|
||||
name: "custom event",
|
||||
url: "http://gigride.live/",
|
||||
domain: "some_site.com",
|
||||
new_visitor: false,
|
||||
uid: UUID.uuid4()
|
||||
}
|
||||
|
||||
conn = conn
|
||||
|> put_req_header("content-type", "text/plain")
|
||||
|> put_req_header("user-agent", @user_agent)
|
||||
|> post("/api/event", Jason.encode!(params))
|
||||
|
||||
event = Repo.one(Plausible.Event)
|
||||
finalize_session(event.user_id)
|
||||
|
||||
assert response(conn, 202) == ""
|
||||
assert event.domain == "some_site.com"
|
||||
end
|
||||
|
||||
test "www. is stripped from hostname", %{conn: conn} do
|
||||
params = %{
|
||||
name: "pageview",
|
||||
|
@ -13,7 +13,7 @@ defmodule PlausibleWeb.Api.InternalControllerTest do
|
||||
end
|
||||
|
||||
test "is READY when site has at least 1 pageview", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
conn = get(conn, "/api/#{site.domain}/status")
|
||||
|
||||
|
@ -6,9 +6,9 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top browsers by new visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, browser: "Chrome", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, browser: "Chrome", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, browser: "Firefox", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, browser: "Chrome", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, browser: "Chrome", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, browser: "Firefox", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/browsers?period=day&date=2019-01-01")
|
||||
|
||||
|
@ -8,10 +8,10 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
||||
test "returns custom event conversions", %{conn: conn, site: site} do
|
||||
insert(:goal, %{domain: site.domain, event_name: "Register"})
|
||||
insert(:goal, %{domain: site.domain, event_name: "Newsletter signup"})
|
||||
insert(:event, name: "Register", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Register", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Newsletter signup", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Irrelevant", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Register", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Register", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Newsletter signup", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Irrelevant", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&date=2019-01-01")
|
||||
|
||||
@ -25,10 +25,10 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
||||
insert(:goal, %{domain: site.domain, page_path: "/success"})
|
||||
insert(:goal, %{domain: site.domain, page_path: "/register"})
|
||||
|
||||
insert(:event, name: "pageview", pathname: "/success", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/register", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/irrelevant", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/success", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/success", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/register", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/irrelevant", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&date=2019-01-01")
|
||||
|
||||
@ -42,9 +42,9 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
||||
insert(:goal, %{domain: site.domain, page_path: "/success"})
|
||||
insert(:goal, %{domain: site.domain, event_name: "Signup"})
|
||||
|
||||
insert(:event, name: "Signup", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&date=2019-01-01")
|
||||
|
||||
@ -62,8 +62,8 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
||||
insert(:goal, %{domain: site.domain, page_path: "/success"})
|
||||
insert(:goal, %{domain: site.domain, event_name: "Signup"})
|
||||
|
||||
insert(:event, name: "Signup", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "pageview", pathname: "/success", domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&date=2019-01-01&filters=#{filters}")
|
||||
|
@ -6,9 +6,9 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top countries by new visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, country_code: "EE", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, country_code: "EE", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, country_code: "GB", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, country_code: "EE", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, country_code: "EE", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, country_code: "GB", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&date=2019-01-01")
|
||||
|
||||
|
@ -6,10 +6,10 @@ defmodule PlausibleWeb.Api.StatsController.CurrentVisitorsTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns unique users in the last 5 minutes", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain)
|
||||
event2 = insert(:pageview, hostname: site.domain, timestamp: Timex.now() |> Timex.shift(minutes: -3))
|
||||
insert(:pageview, hostname: site.domain, user_id: event2.user_id, timestamp: Timex.now() |> Timex.shift(minutes: -4))
|
||||
insert(:pageview, hostname: site.domain, timestamp: Timex.now() |> Timex.shift(minutes: -6))
|
||||
insert(:pageview, domain: site.domain)
|
||||
event2 = insert(:pageview, domain: site.domain, timestamp: Timex.now() |> Timex.shift(minutes: -3))
|
||||
insert(:pageview, domain: site.domain, user_id: event2.user_id, timestamp: Timex.now() |> Timex.shift(minutes: -4))
|
||||
insert(:pageview, domain: site.domain, timestamp: Timex.now() |> Timex.shift(minutes: -6))
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/current-visitors?period=day&date=2019-01-01")
|
||||
|
||||
|
@ -7,8 +7,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "displays visitors for a day", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 23:59:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 23:59:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -22,7 +22,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
|
||||
test "displays hourly stats in configured timezone", %{conn: conn, user: user} do
|
||||
site = insert(:site, members: [user], timezone: "CET") # UTC+1
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 00:00:00]) # Timestamp is in UTC
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 00:00:00]) # Timestamp is in UTC
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -34,8 +34,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "displays visitors for a month", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 12:00:00])
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-31 12:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 12:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-31 12:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=month&date=2019-01-01")
|
||||
|
||||
@ -47,8 +47,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "displays visitors for 6 months", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, hostname: site.domain, timestamp: months_ago(5))
|
||||
insert(:pageview, domain: site.domain)
|
||||
insert(:pageview, domain: site.domain, timestamp: months_ago(5))
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=6mo")
|
||||
|
||||
@ -88,8 +88,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "unique users counts distinct user ids", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 23:59:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 23:59:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -98,8 +98,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "does not count custom events in custom user ids", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:event, name: "Custom", hostname: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:event, name: "Custom", domain: site.domain, timestamp: ~N[2019-01-01 00:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -108,8 +108,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "counts total pageviews even from same user ids", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 23:59:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 00:00:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 23:59:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -118,10 +118,10 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "compares pageviews with previous time period", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-02 02:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-02 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-02")
|
||||
|
||||
@ -130,8 +130,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "calculates bounce rate", %{conn: conn, site: site} do
|
||||
insert(:session, hostname: site.domain, is_bounce: true, start: ~N[2019-01-01 01:00:00])
|
||||
insert(:session, hostname: site.domain, is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: true, start: ~N[2019-01-01 01:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||
|
||||
@ -140,12 +140,12 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "calculates change in bounce rate", %{conn: conn, site: site} do
|
||||
insert(:session, hostname: site.domain, is_bounce: true, start: ~N[2019-01-01 01:00:00])
|
||||
insert(:session, hostname: site.domain, is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: true, start: ~N[2019-01-01 01:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:session, hostname: site.domain, is_bounce: true, start: ~N[2019-01-02 01:00:00])
|
||||
insert(:session, hostname: site.domain, is_bounce: true, start: ~N[2019-01-02 01:00:00])
|
||||
insert(:session, hostname: site.domain, is_bounce: false, start: ~N[2019-01-02 02:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: true, start: ~N[2019-01-02 01:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: true, start: ~N[2019-01-02 01:00:00])
|
||||
insert(:session, domain: site.domain, is_bounce: false, start: ~N[2019-01-02 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-02")
|
||||
|
||||
@ -159,9 +159,9 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns total unique visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01&filters=#{filters}")
|
||||
@ -171,9 +171,9 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "returns converted visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=month&date=2019-01-01&filters=#{filters}")
|
||||
@ -183,9 +183,9 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
end
|
||||
|
||||
test "returns conversion rate", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, user_id: @user_id, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01&filters=#{filters}")
|
||||
|
@ -6,9 +6,9 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns operating systems by new visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, operating_system: "Mac", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, operating_system: "Mac", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, operating_system: "Android", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, operating_system: "Mac", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, operating_system: "Mac", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, operating_system: "Android", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&date=2019-01-01")
|
||||
|
||||
|
@ -6,9 +6,9 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top pages sources by pageviews", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, pathname: "/", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, pathname: "/", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, pathname: "/contact", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/contact", timestamp: ~N[2019-01-01 01:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&date=2019-01-01")
|
||||
|
||||
@ -19,12 +19,12 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do
|
||||
end
|
||||
|
||||
test "calculates bounce rate for pages", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, pathname: "/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, pathname: "/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, pathname: "/contact", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, pathname: "/contact", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:session, hostname: site.domain, entry_page: "/", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, hostname: site.domain, entry_page: "/", is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, entry_page: "/", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, entry_page: "/", is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&date=2019-01-01&include=bounce_rate")
|
||||
|
||||
|
@ -6,10 +6,10 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top referrer sources by new visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", new_visitor: false, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Bing", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", new_visitor: false, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Bing", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/referrers?period=day&date=2019-01-01")
|
||||
|
||||
@ -20,12 +20,12 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
end
|
||||
|
||||
test "calculates bounce rate for referrers", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Bing", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Bing", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:session, hostname: site.domain, referrer_source: "Google", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, hostname: site.domain, referrer_source: "Google", is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, referrer_source: "Google", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, referrer_source: "Google", is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/referrers?period=day&date=2019-01-01&include=bounce_rate")
|
||||
|
||||
@ -40,9 +40,9 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top referrers for a custom goal", %{conn: conn, site: site} do
|
||||
insert(:event, name: "Signup", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/goal/referrers?period=day&date=2019-01-01&filters=#{filters}")
|
||||
@ -53,9 +53,9 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
end
|
||||
|
||||
test "returns top referrers for a pageview goal", %{conn: conn, site: site} do
|
||||
insert(:pageview, pathname: "/register", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/register", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/irrelevant", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, pathname: "/register", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/register", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/irrelevant", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Visit /register"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/goal/referrers?period=day&date=2019-01-01&filters=#{filters}")
|
||||
@ -71,7 +71,7 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
|
||||
test "returns top referrers for a particular source", %{conn: conn, site: site} do
|
||||
insert(:pageview, %{
|
||||
hostname: site.domain,
|
||||
domain: site.domain,
|
||||
referrer: "10words.io/somepage",
|
||||
referrer_source: "10words",
|
||||
new_visitor: true,
|
||||
@ -79,7 +79,7 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
})
|
||||
|
||||
insert(:pageview, %{
|
||||
hostname: site.domain,
|
||||
domain: site.domain,
|
||||
referrer: "10words.io/somepage",
|
||||
referrer_source: "10words",
|
||||
new_visitor: true,
|
||||
@ -87,7 +87,7 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
})
|
||||
|
||||
insert(:pageview, %{
|
||||
hostname: site.domain,
|
||||
domain: site.domain,
|
||||
referrer: "10words.io/some_other_page",
|
||||
referrer_source: "10words",
|
||||
new_visitor: true,
|
||||
@ -106,12 +106,12 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
end
|
||||
|
||||
test "calculates bounce rate for referrer urls", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "10words", referrer: "10words.io/hello", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "10words", referrer: "10words.io/hello", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer_source: "10words", referrer: "10words.io/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "10words", referrer: "10words.io/hello", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "10words", referrer: "10words.io/hello", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer_source: "10words", referrer: "10words.io/", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:session, hostname: site.domain, referrer_source: "10words", referrer: "10words.io/hello", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, hostname: site.domain, referrer_source: "10words", referrer: "10words.io/hello",is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, referrer_source: "10words", referrer: "10words.io/hello", is_bounce: true, start: ~N[2019-01-01 02:00:00])
|
||||
insert(:session, domain: site.domain, referrer_source: "10words", referrer: "10words.io/hello",is_bounce: false, start: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/referrers/10words?period=day&date=2019-01-01&include=bounce_rate")
|
||||
|
||||
@ -126,8 +126,8 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
|
||||
test "gets keywords from Google", %{conn: conn, user: user, site: site} do
|
||||
insert(:google_auth, user: user, user: user,site: site, property: "sc-domain:example.com")
|
||||
insert(:pageview, hostname: site.domain, referrer: "google.com", referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer: "google.com", referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer: "google.com", referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer: "google.com", referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/referrers/Google?period=day&date=2019-01-01")
|
||||
{:ok, terms} = Plausible.Google.Api.Mock.fetch_stats(nil, nil)
|
||||
@ -139,9 +139,9 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
end
|
||||
|
||||
test "enriches twitter referrers with tweets if available", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, referrer: "t.co/some-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer: "t.co/some-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, referrer: "t.co/nonexistent-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer: "t.co/some-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer: "t.co/some-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, referrer: "t.co/nonexistent-link", referrer_source: "Twitter", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
insert(:tweet, link: "t.co/some-link", text: "important tweet")
|
||||
|
||||
@ -159,9 +159,9 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns top referring urls for a custom goal", %{conn: conn, site: site} do
|
||||
insert(:event, name: "Signup", hostname: site.domain, referrer_source: "Twitter", referrer: "a", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, referrer_source: "Twitter", referrer: "a", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:event, name: "Signup", hostname: site.domain, referrer_source: "Twitter", referrer: "b", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, referrer_source: "Twitter", referrer: "a", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, referrer_source: "Twitter", referrer: "a", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:event, name: "Signup", domain: site.domain, referrer_source: "Twitter", referrer: "b", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Signup"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/goal/referrers/Twitter?period=day&date=2019-01-01&filters=#{filters}")
|
||||
@ -176,9 +176,9 @@ defmodule PlausibleWeb.Api.StatsController.ReferrersTest do
|
||||
end
|
||||
|
||||
test "returns top referring urls for a pageview goal", %{conn: conn, site: site} do
|
||||
insert(:pageview, pathname: "/register", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/register", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/irrelevant", hostname: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, pathname: "/register", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/register", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, pathname: "/irrelevant", domain: site.domain, referrer_source: "Google", timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
filters = Jason.encode!(%{goal: "Visit /register"})
|
||||
conn = get(conn, "/api/stats/#{site.domain}/goal/referrers?period=day&date=2019-01-01&filters=#{filters}")
|
||||
|
@ -6,9 +6,9 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "returns screen sizes by new visitors", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain, screen_size: "Desktop", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, hostname: site.domain, screen_size: "Desktop", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, hostname: site.domain, screen_size: "Mobile", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, screen_size: "Desktop", new_visitor: true, timestamp: ~N[2019-01-01 01:00:00])
|
||||
insert(:pageview, domain: site.domain, screen_size: "Desktop", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
insert(:pageview, domain: site.domain, screen_size: "Mobile", new_visitor: true, timestamp: ~N[2019-01-01 02:00:00])
|
||||
|
||||
conn = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&date=2019-01-01")
|
||||
|
||||
|
@ -124,7 +124,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "deletes the site and all pageviews", %{conn: conn, user: user, site: site} do
|
||||
pageview = insert(:pageview, hostname: site.domain)
|
||||
pageview = insert(:pageview, domain: site.domain)
|
||||
insert(:google_auth, user: user, site: site)
|
||||
|
||||
delete(conn, "/#{site.domain}")
|
||||
|
@ -6,14 +6,14 @@ defmodule PlausibleWeb.StatsControllerTest do
|
||||
describe "GET /:website - anonymous user" do
|
||||
test "public site - shows site stats", %{conn: conn} do
|
||||
insert(:site, domain: "public-site.io", public: true)
|
||||
insert(:pageview, hostname: "public-site.io")
|
||||
insert(:pageview, domain: "public-site.io")
|
||||
|
||||
conn = get(conn, "/public-site.io")
|
||||
assert html_response(conn, 200) =~ "stats-react-container"
|
||||
end
|
||||
|
||||
test "can not view stats of a private website", %{conn: conn} do
|
||||
insert(:pageview, hostname: "some-other-site.com")
|
||||
insert(:pageview, domain: "some-other-site.com")
|
||||
|
||||
conn = get(conn, "/some-other-site.com")
|
||||
assert html_response(conn, 404) =~ "There's nothing here"
|
||||
@ -24,14 +24,14 @@ defmodule PlausibleWeb.StatsControllerTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "can view stats of a website I've created", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
conn = get(conn, "/" <> site.domain)
|
||||
assert html_response(conn, 200) =~ "stats-react-container"
|
||||
end
|
||||
|
||||
test "can not view stats of someone else's website", %{conn: conn} do
|
||||
insert(:pageview, hostname: "some-other-site.com")
|
||||
insert(:pageview, domain: "some-other-site.com")
|
||||
|
||||
conn = get(conn, "/some-other-site.com")
|
||||
assert html_response(conn, 404) =~ "There's nothing here"
|
||||
@ -42,7 +42,7 @@ defmodule PlausibleWeb.StatsControllerTest do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "exports graph as csv", %{conn: conn, site: site} do
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
today = Timex.today() |> Timex.format!("{ISOdate}")
|
||||
|
||||
conn = get(conn, "/" <> site.domain <> "/visitors.csv")
|
||||
@ -63,7 +63,7 @@ defmodule PlausibleWeb.StatsControllerTest do
|
||||
test "logs anonymous user in straight away if the link is not password-protected", %{conn: conn} do
|
||||
site = insert(:site)
|
||||
link = insert(:shared_link, site: site)
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
conn = get(conn, "/share/#{link.slug}")
|
||||
assert redirected_to(conn, 302) == "/#{site.domain}"
|
||||
@ -77,7 +77,7 @@ defmodule PlausibleWeb.StatsControllerTest do
|
||||
test "logs anonymous user in with correct password", %{conn: conn} do
|
||||
site = insert(:site)
|
||||
link = insert(:shared_link, site: site, password_hash: Plausible.Auth.Password.hash("password"))
|
||||
insert(:pageview, hostname: site.domain)
|
||||
insert(:pageview, domain: site.domain)
|
||||
|
||||
conn = post(conn, "/share/#{link.slug}/authenticate", %{password: "password"})
|
||||
assert redirected_to(conn, 302) == "/#{site.domain}"
|
||||
|
@ -27,6 +27,7 @@ defmodule Plausible.Factory do
|
||||
|
||||
%Plausible.Session{
|
||||
hostname: hostname,
|
||||
domain: hostname,
|
||||
new_visitor: true,
|
||||
entry_page: "/",
|
||||
user_id: UUID.uuid4(),
|
||||
@ -49,6 +50,7 @@ defmodule Plausible.Factory do
|
||||
|
||||
%Plausible.Event{
|
||||
hostname: hostname,
|
||||
domain: hostname,
|
||||
pathname: "/",
|
||||
new_visitor: true, user_id: UUID.uuid4(),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user