Skip to content

Commit

Permalink
Add tracker feature to automatically track outbound links (#389)
Browse files Browse the repository at this point in the history
* Add tracker feature to automatically track outbound links

* Precompute templates and allow aliases

* Fix /js/analytics.js

* Remove change to tracking code

* Update CHANGELOG
  • Loading branch information
ukutaht authored Nov 3, 2020
1 parent b816d92 commit f0cbf33
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.

### Added
- Ability to add event metadata plausible/analytics#381
- Add tracker module to automatically track outbound links plausible/analytics#389
- Display weekday on the visitor graph plausible/analytics#175

### Changed
Expand Down
55 changes: 0 additions & 55 deletions lib/plausible_web/controllers/tracker_controller.ex

This file was deleted.

1 change: 1 addition & 0 deletions lib/plausible_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ defmodule PlausibleWeb.Endpoint do
extra: "SameSite=Lax"

plug CORSPlug
plug PlausibleWeb.Tracker
plug PlausibleWeb.Router
end
45 changes: 45 additions & 0 deletions lib/plausible_web/plugs/tracker.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule PlausibleWeb.Tracker do
import Plug.Conn
@templates [
"plausible.js",
"plausible.hash.js",
"plausible.hash.outbound-links.js",
"plausible.outbound-links.js",
"p.js"
]
@aliases %{
"plausible.js" => ["analytics.js"],
"plausible.hash.outbound-links.js" => ["plausible.outbound-links.hash.js"]
}

#  1 hour
@max_age 3600

def init(_) do
templates = Enum.reduce(@templates, %{}, fn template_filename, rendered_templates ->
rendered = EEx.eval_file("priv/tracker/js/" <> template_filename, base_url: PlausibleWeb.Endpoint.url())
aliases = Map.get(@aliases, template_filename, [])
[template_filename | aliases]
|> Enum.map(fn filename -> {"/js/" <> filename, rendered} end)
|> Enum.into(%{})
|> Map.merge(rendered_templates)
end)

[templates: templates]
end

def call(conn, templates: templates) do
case templates[conn.request_path] do
found when is_binary(found) -> send_js(conn, found)
nil -> conn
end
end

defp send_js(conn, file) do
conn
|> put_resp_header("cache-control", "max-age=#{@max_age},public")
|> put_resp_header("content-type", "application/javascript")
|> send_resp(200, file)
|> halt()
end
end
5 changes: 0 additions & 5 deletions lib/plausible_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ defmodule PlausibleWeb.Router do
forward "/sent-emails", Bamboo.SentEmailViewerPlug
end

get "/js/plausible.js", PlausibleWeb.TrackerController, :plausible
get "/js/plausible.hash.js", PlausibleWeb.TrackerController, :plausible_hash
get "/js/analytics.js", PlausibleWeb.TrackerController, :plausible
get "/js/p.js", PlausibleWeb.TrackerController, :p

scope "/api/stats", PlausibleWeb.Api do
pipe_through :stats_api

Expand Down
1 change: 1 addition & 0 deletions priv/tracker/js/plausible.hash.outbound-links.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions priv/tracker/js/plausible.outbound-links.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions tracker/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ function compilefile(input, output, templateVars = {}) {

compilefile(relPath('src/plausible.js'), relPath('../priv/tracker/js/plausible.js'))
compilefile(relPath('src/plausible.js'), relPath('../priv/tracker/js/plausible.hash.js'), {hashMode: true})
compilefile(relPath('src/plausible.js'), relPath('../priv/tracker/js/plausible.outbound-links.js'), {outboundLinks: true})
compilefile(relPath('src/plausible.js'), relPath('../priv/tracker/js/plausible.hash.outbound-links.js'), {hash: true, outboundLinks: true})
compilefile(relPath('src/p.js'), relPath('../priv/tracker/js/p.js'))
fs.copyFileSync(relPath('../priv/tracker/js/plausible.js'), relPath('../priv/tracker/js/analytics.js'))
35 changes: 35 additions & 0 deletions tracker/src/plausible.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@
}
}

{{#if outboundLinks}}
function trackOutboundLink(event) {
var link = event.target;
while (link && (typeof link.tagName == 'undefined' || link.tagName.toLowerCase() != 'a' || !link.href)) {
link = link.parentNode;
}

if (link && link.href) {
plausible('Outbound Link: Click', {meta: {url: link.href}})
}

// Delay navigation so that Plausible is notified of the click
if(!link.target || link.target.match(/^_(self|parent|top)$/i)) {
setTimeout(function() { location.href = link.href; }, 150);
event.preventDefault();
}
}

function registerOutboundLinkEvents() {
window.addEventListener('load', function() {
var links = document.getElementsByTagName('a')

for (var i = 0; i < links.length; ++i) {
var link = links[i]
if (link.host !== location.host) {
link.addEventListener('click', trackOutboundLink);
}
}
});
}
{{/if}}

try {
var his = window.history
if (his.pushState) {
Expand All @@ -65,6 +97,9 @@
{{#if hashMode}}
window.addEventListener('hashchange', page)
{{/if}}
{{#if outboundLinks}}
registerOutboundLinkEvents()
{{/if}}


var queue = (window.plausible && window.plausible.q) || []
Expand Down

0 comments on commit f0cbf33

Please sign in to comment.