Skip to content

Commit 6b875d5

Browse files
committed
add umami analytics
1 parent b482213 commit 6b875d5

19 files changed

Lines changed: 133 additions & 37 deletions

404.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ <h5>Mögliche Ursachen</h5>
130130
</section>
131131
</main>
132132
<div hx-get="/partials/footer.html" hx-trigger="load" hx-swap="outerHTML"></div>
133-
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
133+
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"
134+
data-umami-event="scroll_top_click"><i
134135
class="bi bi-arrow-up-short"></i></a>
135136
<div hx-get="/partials/footer-scripts.html" hx-trigger="load" hx-swap="outerHTML"></div>
136137
<script>
@@ -150,4 +151,4 @@ <h5>Mögliche Ursachen</h5>
150151
<script>window.onload = () => { document.body.style.display = "block"; };</script>
151152
</body>
152153

153-
</html>
154+
</html>

assets/js/contact.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
document.addEventListener('alpine:init', () => {
22
Alpine.store('fg', { status: '' });
33

4+
function trackUmami(eventName, payload = {}) {
5+
if (typeof window.apTrackUmami === 'function') {
6+
return window.apTrackUmami(eventName, payload);
7+
}
8+
9+
if (!window.umami || typeof window.umami.track !== 'function') {
10+
return false;
11+
}
12+
13+
if (Object.keys(payload).length > 0) {
14+
window.umami.track(eventName, payload);
15+
} else {
16+
window.umami.track(eventName);
17+
}
18+
19+
return true;
20+
}
21+
422
Alpine.data('formGuard', () => ({
523
start: 0,
624
lastElapsed: 0,
25+
requestPending: false,
26+
requestOutcomeTracked: false,
727

828
init() {
929
this.start = Date.now();
@@ -15,6 +35,9 @@ document.addEventListener('alpine:init', () => {
1535
this.lastElapsed = elapsed;
1636
const hidden = this.$el.querySelector('input[name=\"_elapsed_ms\"]');
1737
if (hidden) hidden.value = String(elapsed);
38+
this.requestPending = true;
39+
this.requestOutcomeTracked = false;
40+
trackUmami('contact_form_submit');
1841
}, { capture: true });
1942

2043
// Fallback: copy hx-post into action if empty
@@ -55,20 +78,34 @@ document.addEventListener('alpine:init', () => {
5578
let data = null;
5679
try { data = JSON.parse(xhr.responseText || ''); } catch { }
5780
if (xhr.status >= 200 && xhr.status < 300 && data && data.ok) {
81+
this.trackRequestOutcome('contact_form_success');
5882
this.setState('sent');
5983
this.$el.reset();
6084
this.start = Date.now();
6185
this.lastElapsed = 0;
6286
} else {
87+
this.trackRequestOutcome('contact_form_error', xhr.status ? { status_code: xhr.status } : {});
6388
this.setState('error');
6489
}
6590
},
6691

6792
sendError(e) {
6893
if (e.target !== this.$el) return;
94+
this.trackRequestOutcome('contact_form_error');
6995
this.setState('error');
7096
},
7197

98+
trackRequestOutcome(eventName, payload = {}) {
99+
// htmx can surface both sendError and afterRequest for the same attempt.
100+
if (!this.requestPending || this.requestOutcomeTracked) {
101+
return;
102+
}
103+
104+
this.requestOutcomeTracked = true;
105+
this.requestPending = false;
106+
trackUmami(eventName, payload);
107+
},
108+
72109
// visual state for CSS fallbacks
73110
setState(state) {
74111
this.$el.setAttribute('data-status', state || 'idle');

assets/js/umami-events.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
(function () {
2+
"use strict";
3+
4+
if (window.__apUmamiEventsInitialized) {
5+
return;
6+
}
7+
8+
window.__apUmamiEventsInitialized = true;
9+
10+
function trackUmami(eventName, payload) {
11+
if (!eventName || !window.umami || typeof window.umami.track !== 'function') {
12+
return false;
13+
}
14+
15+
if (payload && Object.keys(payload).length > 0) {
16+
window.umami.track(eventName, payload);
17+
} else {
18+
window.umami.track(eventName);
19+
}
20+
21+
return true;
22+
}
23+
24+
window.apTrackUmami = trackUmami;
25+
26+
// Use a single delegated listener so HTMX-swapped content is tracked automatically.
27+
document.addEventListener('click', function (event) {
28+
if (event.defaultPrevented) {
29+
return;
30+
}
31+
32+
const target = event.target.closest('[data-umami-event]');
33+
if (!target || target.matches(':disabled')) {
34+
return;
35+
}
36+
37+
trackUmami(target.getAttribute('data-umami-event'));
38+
}, true);
39+
})();

cases/datenbank-entlastet-query-zeiten-halbiert.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,10 @@ <h5><a :href="item.url" rel="noopener" target="_blank" x-text="item.title"></a><
247247
<i :class="$store.toast.isError ? 'bi-x-circle' : 'bi-check2-circle'" class="bi"></i>
248248
<span x-text="$store.toast.message"></span>
249249
</div>
250-
<a class="scroll-top d-flex align-items-center justify-content-center" href="#">
250+
<a class="scroll-top d-flex align-items-center justify-content-center" href="#"
251+
data-umami-event="scroll_top_click">
251252
<i class="bi bi-arrow-up-short"></i>
252253
</a>
253254
</body>
254255

255-
</html>
256+
</html>

cases/microservice-unter-last-stabilisiert.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,10 @@ <h5><a :href="item.url" rel="noopener" target="_blank" x-text="item.title"></a><
238238
<i :class="$store.toast.isError ? 'bi-x-circle' : 'bi-check2-circle'" class="bi"></i>
239239
<span x-text="$store.toast.message"></span>
240240
</div>
241-
<a class="scroll-top d-flex align-items-center justify-content-center" href="#">
241+
<a class="scroll-top d-flex align-items-center justify-content-center" href="#"
242+
data-umami-event="scroll_top_click">
242243
<i class="bi bi-arrow-up-short"></i>
243244
</a>
244245
</body>
245246

246-
</html>
247+
</html>

cases/preislogik-konsolidiert.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ <h5><a :href="item.url" rel="noopener" target="_blank" x-text="item.title"></a><
225225
<i :class="$store.toast.isError ? 'bi-x-circle' : 'bi-check2-circle'" class="bi"></i>
226226
<span x-text="$store.toast.message"></span>
227227
</div>
228-
<a class="scroll-top d-flex align-items-center justify-content-center" href="#">
228+
<a class="scroll-top d-flex align-items-center justify-content-center" href="#"
229+
data-umami-event="scroll_top_click">
229230
<i class="bi bi-arrow-up-short"></i>
230231
</a>
231232
</body>
232233

233-
</html>
234+
</html>

cases/wissensinseln-konsolidiert-obsidian-git-sync.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,10 @@ <h5><a :href="item.url" rel="noopener" target="_blank" x-text="item.title"></a><
259259
<i :class="$store.toast.isError ? 'bi-x-circle' : 'bi-check2-circle'" class="bi"></i>
260260
<span x-text="$store.toast.message"></span>
261261
</div>
262-
<a class="scroll-top d-flex align-items-center justify-content-center" href="#">
262+
<a class="scroll-top d-flex align-items-center justify-content-center" href="#"
263+
data-umami-event="scroll_top_click">
263264
<i class="bi bi-arrow-up-short"></i>
264265
</a>
265266
</body>
266267

267-
</html>
268+
</html>

index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@
157157
<div hx-get="/partials/contact.html" hx-trigger="load" hx-swap="outerHTML"></div>
158158
</main>
159159
<div hx-get="/partials/footer.html" hx-trigger="load" hx-swap="outerHTML"></div>
160-
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
160+
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"
161+
data-umami-event="scroll_top_click"><i
161162
class="bi bi-arrow-up-short"></i></a>
162163
<!--
163164
<div hx-get="/partials/footer-scripts.html" hx-trigger="load" hx-swap="outerHTML"></div>
@@ -167,6 +168,7 @@
167168
<script src="/assets/vendor/waypoints/noframework.waypoints.js"></script>
168169
<script src="/assets/vendor/imagesloaded/imagesloaded.pkgd.min.js"></script>
169170
<script src="/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
171+
<script src="/assets/js/umami-events.js"></script>
170172
<script src="/assets/js/main.js"></script>
171173
<script>
172174
document.addEventListener('DOMContentLoaded', function () {

landing/freelancer-roi-check/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ <h4>Hinweis</h4>
185185
</section>
186186
</main>
187187
<div hx-get="/partials/footer.html" hx-trigger="load" hx-swap="outerHTML"></div>
188-
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
188+
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"
189+
data-umami-event="scroll_top_click"><i
189190
class="bi bi-arrow-up-short"></i></a>
190191
<div hx-get="/partials/footer-scripts.html" hx-trigger="load" hx-swap="outerHTML"></div>
191192
<script>window.onload = () => { document.body.style.display = "block"; };</script>

landing/hourly-rate/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ <h4>Hinweis</h4>
185185
</section>
186186
</main>
187187
<div hx-get="/partials/footer.html" hx-trigger="load" hx-swap="outerHTML"></div>
188-
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
188+
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"
189+
data-umami-event="scroll_top_click"><i
189190
class="bi bi-arrow-up-short"></i></a>
190191
<div hx-get="/partials/footer-scripts.html" hx-trigger="load" hx-swap="outerHTML"></div>
191192
<script>window.onload = () => { document.body.style.display = "block"; };</script>

0 commit comments

Comments
 (0)