Show current visitors

This commit is contained in:
Uku Taht 2019-09-04 16:08:01 +01:00
parent 9868392818
commit 00d02faad0
6 changed files with 82 additions and 1 deletions

View File

@ -125,4 +125,13 @@ if (domainEl) {
router.updateLinkHandlers()
})
})
setInterval(function() {
fetch(`/api/${domain}/current-visitors`)
.then(res => res.json())
.then((res) => {
console.log(res)
document.getElementById('current-visitors').innerHTML = res
})
}, 10000)
}

View File

@ -181,6 +181,15 @@ defmodule Plausible.Stats do
)
end
def current_visitors(site) do
Repo.one(
from p in Plausible.Pageview,
where: p.inserted_at >= fragment("(now() at time zone 'utc') - '5 minutes'::interval"),
where: p.hostname == ^site.domain,
select: count(p.user_id, :distinct)
)
end
defp base_query(site, query) do
{:ok, first} = NaiveDateTime.new(query.date_range.first, ~T[00:00:00])
first_datetime = Timex.to_datetime(first, site.timezone)

View File

@ -23,12 +23,14 @@ defmodule PlausibleWeb.StatsController do
{conn, params} = fetch_period(conn, site)
query = Stats.Query.from(site.timezone, params)
current_visitors = Stats.current_visitors(site)
conn
|> assign(:skip_plausible_tracking, !demo)
|> render("stats.html",
site: site,
query: query,
current_visitors: current_visitors,
title: "Plausible · " <> site.domain
)
else
@ -295,6 +297,16 @@ defmodule PlausibleWeb.StatsController do
end
end
def current_visitors(conn, %{"domain" => domain}) do
site = Repo.get_by(Plausible.Site, domain: domain)
if site && current_user_can_access?(conn, site) do
json(conn, Stats.current_visitors(site))
else
render_error(conn, 404)
end
end
defp current_user_can_access?(_conn, %Plausible.Site{public: true}) do
true
end

View File

@ -42,6 +42,7 @@ defmodule PlausibleWeb.Router do
get "/:domain/operating-systems", StatsController, :operating_systems
get "/:domain/browsers", StatsController, :browsers
get "/:domain/compare", StatsController, :compare
get "/:domain/current-visitors", StatsController, :current_visitors
end
scope "/", PlausibleWeb do

View File

@ -1,7 +1,15 @@
<div class="pt-12"></div>
<div class="container pb-32" data-site-domain="<%= @site.domain %>">
<div class="w-full sm:flex justify-between items-center">
<h2 class="text-center sm:text-left sm:mr-8">Analytics for <%= link(@site.domain, to: "//" <> @site.domain, target: "_blank") %></h2>
<div class="w-full sm:flex items-center">
<h2 class="text-center sm:text-left sm:mr-8">Analytics for <%= link(@site.domain, to: "//" <> @site.domain, target: "_blank") %></h2>
<div class="text-sm font-bold text-grey-darker">
<svg class="w-2 mr-1 fill-current text-green" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8"/>
</svg>
<span id="current-visitors"><%= @current_visitors %></span> current visitors
</div>
</div>
<div class="mt-4 sm:mt-0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>

View File

@ -143,6 +143,48 @@ defmodule Plausible.StatsTest do
end
end
describe "current_visitors" do
test "counts user ids seen in the last 5 minutes" do
site = insert(:site)
insert(:pageview, %{
hostname: site.domain,
user_id: UUID.uuid4(),
})
insert(:pageview, %{
hostname: site.domain,
user_id: UUID.uuid4(),
inserted_at: Timex.now() |> Timex.shift(minutes: -4)
})
insert(:pageview, %{
hostname: site.domain,
user_id: UUID.uuid4(),
inserted_at: Timex.now() |> Timex.shift(minutes: -6)
})
assert Stats.current_visitors(site) == 2
end
test "counts unique user ids" do
site = insert(:site)
id = UUID.uuid4()
insert(:pageview, %{
hostname: site.domain,
user_id: id,
})
insert(:pageview, %{
hostname: site.domain,
user_id: id,
})
assert Stats.current_visitors(site) == 1
end
end
defp months_ago(months) do
Timex.now() |> Timex.shift(months: -months)
end