@huloglobal/vendure-plugin-visitor-analytics 0.8.4 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/hulo-global-logo.svg +26 -0
- package/logo.svg +20 -0
- package/package.json +5 -3
- package/ui/components/visitors.component.ts +89 -6
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ documented here. The format follows
|
|
|
5
5
|
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project
|
|
6
6
|
adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.4] — 2026-07-04
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `GET /ees/abandoned-carts` now includes each cart's parsed
|
|
12
|
+
`items` array plus a short server-rendered `itemsPreview`
|
|
13
|
+
string ("Windows 10 Pro, Office 2021 Pro +2 more"), sorted by
|
|
14
|
+
quantity descending. Admin can see WHAT was abandoned without
|
|
15
|
+
clicking through to the detail endpoint.
|
|
16
|
+
- `GET /ees/abandoned-carts/:id` fills in missing `name` (and
|
|
17
|
+
`productId` when it can) on every item by looking up
|
|
18
|
+
`product_variant_translation` / `product_translation`. Only
|
|
19
|
+
fills where the storefront snapshot didn't already capture a
|
|
20
|
+
name — a stored name at cart time is more accurate than a live
|
|
21
|
+
catalog lookup (products can be renamed after abandonment).
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- List endpoint drops the raw `itemsJson` string from its
|
|
25
|
+
response — clients that need the JSON blob can hit the detail
|
|
26
|
+
endpoint. Response payload stays lean.
|
|
27
|
+
|
|
8
28
|
## [0.8.3] — 2026-07-04
|
|
9
29
|
|
|
10
30
|
### Added
|
|
@@ -276,6 +296,7 @@ adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
276
296
|
- Licence verification via `@huloglobal/vendure-licence-sdk` with
|
|
277
297
|
revocation polling.
|
|
278
298
|
|
|
299
|
+
[0.8.4]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.8.4
|
|
279
300
|
[0.8.3]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.8.3
|
|
280
301
|
[0.8.2]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.8.2
|
|
281
302
|
[0.8.1]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.8.1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="HULO Global">
|
|
2
|
+
<title>HULO Global</title>
|
|
3
|
+
<!-- Shared HULO frame: rounded 14px navy square. Everything below
|
|
4
|
+
is the HG monogram tuned so both letters read cleanly at 20px
|
|
5
|
+
favicon size without ligature ambiguity. -->
|
|
6
|
+
<rect width="64" height="64" rx="14" fill="#0f1419"/>
|
|
7
|
+
|
|
8
|
+
<!-- H — two verticals + a crossbar. Kept slim (5px stroke on 64px
|
|
9
|
+
viewport) so the counter-space between letters stays legible. -->
|
|
10
|
+
<path d="M14 16 h5 v13 h11 v-13 h5 v32 h-5 v-14 h-11 v14 h-5 z"
|
|
11
|
+
fill="#ffffff"/>
|
|
12
|
+
|
|
13
|
+
<!-- G — a rounded arc that reads as an incomplete circle plus the
|
|
14
|
+
amber tick that closes it off. The tick is the HULO accent
|
|
15
|
+
colour so the mark carries brand pigment even at tiny sizes. -->
|
|
16
|
+
<path d="M50 24
|
|
17
|
+
A11 11 0 1 0 50 42
|
|
18
|
+
L50 34
|
|
19
|
+
L44 34
|
|
20
|
+
L44 30"
|
|
21
|
+
fill="none" stroke="#ffffff" stroke-width="4.5"
|
|
22
|
+
stroke-linecap="round" stroke-linejoin="round"/>
|
|
23
|
+
<!-- Amber accent tick — closes the G bowl and provides the brand
|
|
24
|
+
colour anchor. Drawn last so it lays on top. -->
|
|
25
|
+
<circle cx="50" cy="33" r="2.5" fill="#f59e0b"/>
|
|
26
|
+
</svg>
|
package/logo.svg
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="HULO Visitor Analytics">
|
|
2
|
+
<title>HULO Visitor Analytics</title>
|
|
3
|
+
<!-- HULO frame. -->
|
|
4
|
+
<rect width="64" height="64" rx="14" fill="#0f1419"/>
|
|
5
|
+
<!-- Bar chart — four rising bars in white. Left-most is the
|
|
6
|
+
shortest; each column steps up so growth reads at any size.
|
|
7
|
+
Bars sit on an implied baseline at y=48. -->
|
|
8
|
+
<rect x="14" y="34" width="7" height="14" rx="1.5" fill="#ffffff"/>
|
|
9
|
+
<rect x="24" y="28" width="7" height="20" rx="1.5" fill="#ffffff"/>
|
|
10
|
+
<rect x="34" y="22" width="7" height="26" rx="1.5" fill="#ffffff"/>
|
|
11
|
+
<rect x="44" y="16" width="7" height="32" rx="1.5" fill="#ffffff"/>
|
|
12
|
+
<!-- Trend line — amber diagonal that connects the bar tops with
|
|
13
|
+
a small end-point dot. This is the "analytics" signal — it
|
|
14
|
+
turns "bar chart" into "line-of-improvement" and the amber
|
|
15
|
+
colour ties the mark to the HULO brand. -->
|
|
16
|
+
<polyline points="17.5,34 27.5,28 37.5,22 47.5,16"
|
|
17
|
+
fill="none" stroke="#f59e0b" stroke-width="2.5"
|
|
18
|
+
stroke-linecap="round" stroke-linejoin="round"/>
|
|
19
|
+
<circle cx="47.5" cy="16" r="2.5" fill="#f59e0b"/>
|
|
20
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huloglobal/vendure-plugin-visitor-analytics",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "Full-funnel visitor analytics for Vendure storefronts
|
|
3
|
+
"version": "0.8.6",
|
|
4
|
+
"description": "Full-funnel visitor analytics for Vendure storefronts — pageviews, time-on-page, session journey, exit pages, funnel drop-off, and per-visitor profile drawer with parsed user-agent + MaxMind GeoLite2 enrichment. Auto-issues visitor + session cookies on first request; logs guest and signed-in events against the same visitor id so the journey survives login.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"author": "Wayne Garrison <wayne@garrison.me.uk>",
|
|
7
7
|
"homepage": "https://github.com/exceeded/vendure-plugin-visitor-analytics",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"ui",
|
|
17
17
|
"README.md",
|
|
18
18
|
"CHANGELOG.md",
|
|
19
|
-
"LICENSE"
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"logo.svg",
|
|
21
|
+
"hulo-global-logo.svg"
|
|
20
22
|
],
|
|
21
23
|
"scripts": {
|
|
22
24
|
"build": "tsc -p tsconfig.json",
|
|
@@ -41,20 +41,64 @@ interface VisitorProfile {
|
|
|
41
41
|
selector: 'ees-visitors',
|
|
42
42
|
standalone: false,
|
|
43
43
|
template: `
|
|
44
|
+
<!-- ── HULO brand hero — shared pattern across every HULO plugin. -->
|
|
44
45
|
<vdr-page-block>
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
|
|
46
|
+
<div class="hulo-hero">
|
|
47
|
+
<div class="hulo-hero-logo" aria-hidden="true">
|
|
48
|
+
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
|
49
|
+
<rect width="64" height="64" rx="14" fill="#0f1419"/>
|
|
50
|
+
<rect x="14" y="34" width="7" height="14" rx="1.5" fill="#ffffff"/>
|
|
51
|
+
<rect x="24" y="28" width="7" height="20" rx="1.5" fill="#ffffff"/>
|
|
52
|
+
<rect x="34" y="22" width="7" height="26" rx="1.5" fill="#ffffff"/>
|
|
53
|
+
<rect x="44" y="16" width="7" height="32" rx="1.5" fill="#ffffff"/>
|
|
54
|
+
<polyline points="17.5,34 27.5,28 37.5,22 47.5,16" fill="none" stroke="#f59e0b" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
55
|
+
<circle cx="47.5" cy="16" r="2.5" fill="#f59e0b"/>
|
|
56
|
+
</svg>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="hulo-hero-text">
|
|
59
|
+
<h2 class="hulo-hero-title">Visitor journey</h2>
|
|
60
|
+
<p class="hulo-hero-sub">Live visitor count plus the funnel from landing → product → cart → checkout → order. Change the date range on the right.</p>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="hulo-hero-actions">
|
|
48
63
|
<span class="range">
|
|
49
|
-
Range:
|
|
50
64
|
<button class="btn btn-sm btn-link" *ngFor="let d of [7, 30, 90, 365]"
|
|
51
65
|
(click)="setDays(d)" [class.active]="days === d">{{ d }}d</button>
|
|
52
66
|
</span>
|
|
67
|
+
<button class="btn btn-link hulo-help-btn" (click)="helpOpen = !helpOpen" [attr.aria-expanded]="helpOpen">
|
|
68
|
+
<clr-icon shape="help"></clr-icon><span>Help</span>
|
|
69
|
+
</button>
|
|
53
70
|
<button class="btn btn-link" (click)="loadAll()" [disabled]="loading">
|
|
54
71
|
<clr-icon shape="refresh"></clr-icon> Refresh
|
|
55
72
|
</button>
|
|
56
|
-
</
|
|
57
|
-
</
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</vdr-page-block>
|
|
76
|
+
|
|
77
|
+
<vdr-page-block *ngIf="helpOpen">
|
|
78
|
+
<div class="hulo-help-drawer">
|
|
79
|
+
<div class="hulo-help-grid">
|
|
80
|
+
<div class="hulo-help-card">
|
|
81
|
+
<div class="hulo-help-num">1</div>
|
|
82
|
+
<h4>Add the one-liner script to your storefront</h4>
|
|
83
|
+
<p>Drop <code><script src="/ees/hulo.js"></code> in your site head. It handles session + page tracking automatically.</p>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="hulo-help-card">
|
|
86
|
+
<div class="hulo-help-num">2</div>
|
|
87
|
+
<h4>Watch the funnel</h4>
|
|
88
|
+
<p>Each stage shows visitors + drop-off %. Big gaps usually point to a specific broken UX or slow page.</p>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="hulo-help-card">
|
|
91
|
+
<div class="hulo-help-num">3</div>
|
|
92
|
+
<h4>Compare over time</h4>
|
|
93
|
+
<p>Change the 7d / 30d / 90d / 365d range in the header. All numbers, series and top-country lists follow.</p>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="hulo-help-links">
|
|
97
|
+
<a href="https://huloglobal.com/vendure-plugins/visitor-analytics/docs/" target="_blank">Full docs ↗</a>
|
|
98
|
+
<a href="https://huloglobal.com/vendure-plugins/visitor-analytics/" target="_blank">Plugin page ↗</a>
|
|
99
|
+
<a href="mailto:support@huloglobal.com">Email support</a>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
58
102
|
</vdr-page-block>
|
|
59
103
|
|
|
60
104
|
<vdr-page-block *ngIf="updateBanner">
|
|
@@ -398,6 +442,43 @@ interface VisitorProfile {
|
|
|
398
442
|
styles: [`
|
|
399
443
|
:host { color: var(--color-text-100, inherit); display: block; }
|
|
400
444
|
|
|
445
|
+
/* ── HULO shared hero + help pattern ─────────────────────── */
|
|
446
|
+
.hulo-hero {
|
|
447
|
+
display: flex; align-items: center; gap: 18px;
|
|
448
|
+
padding: 20px 22px; border-radius: 14px;
|
|
449
|
+
background: linear-gradient(135deg, #0f1419 0%, #1e293b 100%);
|
|
450
|
+
color: #fff;
|
|
451
|
+
box-shadow: 0 1px 3px rgba(15,23,42,.15), 0 8px 24px rgba(15,23,42,.08);
|
|
452
|
+
}
|
|
453
|
+
.hulo-hero-logo { flex: 0 0 auto; width: 56px; height: 56px; }
|
|
454
|
+
.hulo-hero-logo svg { width: 100%; height: 100%; display: block; }
|
|
455
|
+
.hulo-hero-text { flex: 1 1 auto; min-width: 0; }
|
|
456
|
+
.hulo-hero-title { color: #fff; font-size: 22px; font-weight: 700; margin: 0; letter-spacing: -0.01em; }
|
|
457
|
+
.hulo-hero-sub { color: #cbd5e1; font-size: 13px; line-height: 1.5; margin: 4px 0 0; max-width: 640px; }
|
|
458
|
+
.hulo-hero-actions { display: flex; gap: 6px; align-items: center; flex: 0 0 auto; }
|
|
459
|
+
.hulo-hero-actions .btn { color: #f8fafc; }
|
|
460
|
+
.hulo-hero-actions .btn:hover { color: #f59e0b; }
|
|
461
|
+
.hulo-help-btn clr-icon { margin-right: 4px; }
|
|
462
|
+
.hulo-help-drawer {
|
|
463
|
+
background: #fffbeb; border: 1px solid #fde68a; border-radius: 12px;
|
|
464
|
+
padding: 20px 22px; color: #451a03;
|
|
465
|
+
}
|
|
466
|
+
.hulo-help-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
|
|
467
|
+
.hulo-help-card { background: #ffffff; border-radius: 10px; padding: 16px; }
|
|
468
|
+
.hulo-help-num { width: 24px; height: 24px; border-radius: 999px;
|
|
469
|
+
background: #f59e0b; color: #fff; font-weight: 700; font-size: 13px;
|
|
470
|
+
display: grid; place-items: center; margin-bottom: 8px; }
|
|
471
|
+
.hulo-help-card h4 { margin: 0 0 4px; font-size: 14px; color: #0f172a; }
|
|
472
|
+
.hulo-help-card p { margin: 0; font-size: 13px; line-height: 1.5; color: #475569; }
|
|
473
|
+
.hulo-help-card code { background: #f1f5f9; padding: 2px 6px; border-radius: 4px; font-size: 12px; }
|
|
474
|
+
.hulo-help-links { margin-top: 16px; padding-top: 14px; border-top: 1px solid #fde68a; display: flex; gap: 18px; flex-wrap: wrap; font-size: 13px; }
|
|
475
|
+
.hulo-help-links a { color: #b45309; text-decoration: none; font-weight: 600; }
|
|
476
|
+
.hulo-help-links a:hover { text-decoration: underline; }
|
|
477
|
+
@media (max-width: 640px) {
|
|
478
|
+
.hulo-hero { flex-wrap: wrap; }
|
|
479
|
+
.hulo-hero-actions { width: 100%; justify-content: flex-end; }
|
|
480
|
+
}
|
|
481
|
+
|
|
401
482
|
.update-banner {
|
|
402
483
|
display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap;
|
|
403
484
|
padding: 12px 16px; border-radius: 8px;
|
|
@@ -588,6 +669,8 @@ export class VisitorsComponent implements OnInit, OnDestroy {
|
|
|
588
669
|
profileLoading = false;
|
|
589
670
|
|
|
590
671
|
updateBanner: { packageName: string; current: string; latest: string; isMajor: boolean } | null = null;
|
|
672
|
+
/** Toggles the shared HULO help drawer under the hero. */
|
|
673
|
+
helpOpen = false;
|
|
591
674
|
private dismissKey = 'huloglobal-visitor-analytics-update-dismissed';
|
|
592
675
|
|
|
593
676
|
constructor(
|