feat: add primaryLabel() for behavior-based visitor identification

Priority: buyer > cart > demo download > demo browse > returning > visitor.
Replaces random Stripe-style names with informative labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 15:18:37 +00:00
parent ffb57aeece
commit 64fd1f8330

View File

@@ -119,6 +119,8 @@ class VisitorNickname
// Demo activity
if (!empty($d['has_demo'])) {
$tags[] = 'demo-downloader';
} elseif (!empty($d['has_demo_page'])) {
$tags[] = 'demo-browser';
}
// Browsing depth
@@ -200,6 +202,49 @@ class VisitorNickname
return self::behaviorTags($row);
}
/**
* Pick the most informative single label for a visitor.
*
* Priority: order > cart > demo download > demo boot > returning visitor > visitor
*
* @param array $tags Output of behaviorTags()
* @param int $pages Total pages viewed
* @param int $sessions Number of sessions
* @return string Human-readable label, e.g. "Cart Abandoner"
*/
public static function primaryLabel(array $tags, int $pages = 0, int $sessions = 0): string
{
// Priority map — business funnel order, first match wins
$priority = [
'buyer' => 'Buyer',
'checkout-started' => 'Checkout Started',
'cart-abandoner' => 'Cart Abandoner',
'demo-downloader' => 'Demo Downloader',
'demo-browser' => 'Demo Browser',
'returning' => 'Returning Visitor',
'customer' => 'Customer',
'deep-browser' => 'Engaged Visitor',
'engaged' => 'Engaged Visitor',
'product-browser' => 'Product Browser',
'content-reader' => 'Content Reader',
'searcher' => 'Searcher',
'first-visit' => 'New Visitor',
];
foreach ($priority as $tag => $label) {
if (in_array($tag, $tags)) {
return $label;
}
}
// Fallback
if ($pages > 1) {
return 'Visitor (' . $pages . 'p)';
}
return 'Visitor';
}
/**
* Render behavior tags as HTML badges.
*