2020-11-03 12:09:50 +03:00
|
|
|
defmodule PlausibleWeb.Tracker do
|
|
|
|
import Plug.Conn
|
2020-11-03 12:35:08 +03:00
|
|
|
use Agent
|
2020-11-03 12:20:11 +03:00
|
|
|
|
2022-03-31 13:52:09 +03:00
|
|
|
base_variants = [
|
|
|
|
"hash",
|
|
|
|
"outbound-links",
|
|
|
|
"exclusions",
|
|
|
|
"compat",
|
|
|
|
"local",
|
|
|
|
"manual",
|
2022-04-25 10:56:11 +03:00
|
|
|
"file-downloads",
|
2023-03-27 17:50:15 +03:00
|
|
|
"pageview-props",
|
2023-06-14 12:23:11 +03:00
|
|
|
"tagged-events",
|
|
|
|
"revenue"
|
2022-03-31 13:52:09 +03:00
|
|
|
]
|
|
|
|
|
2021-05-18 11:36:12 +03:00
|
|
|
# Generates Power Set of all variants
|
|
|
|
variants =
|
|
|
|
1..Enum.count(base_variants)
|
|
|
|
|> Enum.map(fn x ->
|
|
|
|
Combination.combine(base_variants, x)
|
|
|
|
|> Enum.map(fn y -> Enum.sort(y) |> Enum.join(".") end)
|
|
|
|
end)
|
|
|
|
|> List.flatten()
|
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
@base_filenames ["plausible", "script", "analytics"]
|
|
|
|
@files_available ["plausible.js", "p.js"] ++ Enum.map(variants, fn v -> "plausible.#{v}.js" end)
|
2021-05-18 11:36:12 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
def init(opts) do
|
|
|
|
Keyword.merge(opts, files_available: MapSet.new(@files_available))
|
|
|
|
end
|
2021-05-18 11:36:12 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
def call(conn, files_available: files_available) do
|
|
|
|
filename =
|
|
|
|
case conn.request_path do
|
|
|
|
"/js/p.js" ->
|
|
|
|
"p.js"
|
2021-05-18 11:36:12 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
"/js/" <> requested_filename ->
|
|
|
|
sorted_script_variant(requested_filename)
|
2020-11-03 12:09:50 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
_ ->
|
|
|
|
nil
|
|
|
|
end
|
2020-11-03 12:20:11 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
if filename && MapSet.member?(files_available, filename) do
|
|
|
|
location = Application.app_dir(:plausible, "priv/tracker/js/" <> filename)
|
2020-11-03 12:09:50 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
conn
|
|
|
|
|> put_resp_header("content-type", "application/javascript")
|
|
|
|
|> put_resp_header("x-content-type-options", "nosniff")
|
|
|
|
|> put_resp_header("cross-origin-resource-policy", "cross-origin")
|
|
|
|
|> put_resp_header("access-control-allow-origin", "*")
|
|
|
|
|> put_resp_header("cache-control", "public, max-age=86400, must-revalidate")
|
|
|
|
|> send_file(200, location)
|
|
|
|
|> halt()
|
|
|
|
else
|
|
|
|
conn
|
|
|
|
end
|
2020-11-03 12:09:50 +03:00
|
|
|
end
|
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
defp sorted_script_variant(requested_filename) do
|
|
|
|
case String.split(requested_filename, ".") do
|
|
|
|
[base_filename | rest] when base_filename in @base_filenames ->
|
|
|
|
sorted_variants =
|
|
|
|
rest
|
|
|
|
|> List.delete("js")
|
|
|
|
|> Enum.sort()
|
2020-12-29 16:17:27 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
Enum.join(["plausible"] ++ sorted_variants ++ ["js"], ".")
|
2020-11-03 12:09:50 +03:00
|
|
|
|
2022-05-27 10:11:40 +03:00
|
|
|
_ ->
|
|
|
|
nil
|
2021-05-18 15:24:45 +03:00
|
|
|
end
|
2020-11-03 12:09:50 +03:00
|
|
|
end
|
|
|
|
end
|