Overview
The Tagging module handles analytics tracking and event tagging for user interactions. It manages user consent, session tracking, query tagging, and integration with analytics platforms for search behavior analysis.
State
The Tagging module maintains the following state:
User consent status for tracking (null = not set, true = granted, false = denied)
Whether no-results events should be tracked
Current query tagging information from search response
Tracking info for tooling events (display, add to cart)
Module configuration options
Configuration
Session time-to-live in milliseconds (default: 30 minutes)
Debounce time before sending query tagging events
storageKey
string | null
default: "null"
Key for storing tagging data in browser storage
storageTTLMs
number | null
default: "null"
Time-to-live for stored tagging data
Getters
The Tagging module has no getters (uses direct state access).
Mutations
setConsent
(state, consent: boolean) => void
Set user tracking consent
setQueryTaggingInfo
(state, info: TaggingRequest) => void
Update query tagging information
setNoResultsTaggingEnabled
(state, module: string) => void
Enable no-results tagging for semantic queries or related prompts
setConfig
(state, config: Partial<TaggingConfig>) => void
Update configuration
mergeConfig
(state, config: Partial<TaggingConfig>) => void
Merge configuration with existing config
Actions
track
(context, event: TaggingEvent) => void
Track an analytics event
Events Tracked
Common events you can track:
User submitted a search query
User clicked a search result
UserClickedARecommendation
{ recommendation: Result }
User clicked a recommendation
User selected/deselected a filter
User clicked a history query
User added a product to cart
Results were displayed to user
No results were found for query
Usage Examples
Request Consent
import { useStore } from 'vuex'
const store = useStore ()
// Request and set user consent
const userConsent = await requestTrackingConsent ()
store . commit ( 'x/tagging/setConsent' , userConsent )
// Check consent before tracking
const hasConsent = store . state . x . tagging . consent
if ( hasConsent ) {
// Track events
}
Track Search Query
// Track when user submits a query
store . dispatch ( 'x/tagging/track' , {
event: 'UserAcceptedAQuery' ,
query: 'running shoes' ,
timestamp: Date . now ()
})
Track Result Click
import type { Result } from '@empathyco/x-types'
const result : Result = {
id: 'product-123' ,
name: 'Running Shoes' ,
url: '/products/running-shoes' ,
// ... other properties
}
store . dispatch ( 'x/tagging/track' , {
event: 'UserClickedAResult' ,
result ,
position: 3 , // Position in results list
query: store . state . x . search . query
})
Track Filter Interactions
import type { Filter } from '@empathyco/x-types'
const filter : Filter = {
id: 'brand:nike' ,
facetId: 'brand' ,
label: 'Nike' ,
selected: true ,
modelName: 'SimpleFilter'
}
store . dispatch ( 'x/tagging/track' , {
event: 'UserClickedAFilter' ,
filter ,
action: filter . selected ? 'select' : 'deselect'
})
Track Add to Cart
store . dispatch ( 'x/tagging/track' , {
event: 'UserAddedToCart' ,
result: product ,
quantity: 1 ,
query: store . state . x . search . query
})
Component Integration
< template >
< div class = "result-card" @ click = " handleClick " >
< img : src = " result . images [ 0 ] " : alt = " result . name " />
< h3 > {{ result . name }} </ h3 >
< p > {{ result . price ?. value }} </ p >
< button @ click . stop = " handleAddToCart " > Add to Cart </ button >
</ div >
</ template >
< script setup lang = "ts" >
import { useStore } from 'vuex'
import type { Result } from '@empathyco/x-types'
interface Props {
result : Result
position : number
}
const props = defineProps < Props >()
const store = useStore ()
const handleClick = () => {
// Track click
store . dispatch ( 'x/tagging/track' , {
event: 'UserClickedAResult' ,
result: props . result ,
position: props . position ,
query: store . state . x . search . query
})
// Navigate to product
window . location . href = props . result . url
}
const handleAddToCart = () => {
// Track add to cart
store . dispatch ( 'x/tagging/track' , {
event: 'UserAddedToCart' ,
result: props . result ,
query: store . state . x . search . query
})
// Add to cart logic
store . dispatch ( 'cart/addItem' , props . result )
}
</ script >
Track Display Events
< template >
< div >
< div
v-for = " ( result , index ) in visibleResults "
: key = " result . id "
v-observe-visibility = " ( isVisible ) => onVisibilityChange ( result , index , isVisible ) "
>
< ResultCard : result = " result " />
</ div >
</ div >
</ template >
< script setup lang = "ts" >
import { ref , onMounted } from 'vue'
import { useStore } from 'vuex'
import type { Result } from '@empathyco/x-types'
const store = useStore ()
const displayedResults = ref < Set < string >>( new Set ())
const onVisibilityChange = (
result : Result ,
position : number ,
isVisible : boolean
) => {
if ( isVisible && ! displayedResults . value . has ( result . id )) {
displayedResults . value . add ( result . id )
store . dispatch ( 'x/tagging/track' , {
event: 'UserDisplayedResult' ,
result ,
position ,
query: store . state . x . search . query
})
}
}
</ script >
Query Tagging Integration
import { watch } from 'vue'
// Update query tagging info from search response
watch (
() => store . state . x . search . queryTagging ,
( queryTagging ) => {
if ( queryTagging ) {
store . commit ( 'x/tagging/setQueryTaggingInfo' , queryTagging )
}
}
)
// Access query tagging for tracking requests
const queryTaggingInfo = store . state . x . tagging . queryTaggingInfo
if ( queryTaggingInfo ) {
// Include in tracking request
const trackingData = {
event: 'UserClickedAResult' ,
result ,
tagging: queryTaggingInfo
}
}
No Results Tracking
import { watch } from 'vue'
// Track when no results are displayed
watch (
() => store . state . x . search . isNoResults ,
( isNoResults ) => {
if ( isNoResults ) {
const query = store . state . x . search . query
store . dispatch ( 'x/tagging/track' , {
event: 'NoResultsDisplayed' ,
query ,
filters: store . getters [ 'x/facets/selectedFilters' ]
})
}
}
)
Session Tracking
// Configure session tracking
store . commit ( 'x/tagging/setConfig' , {
sessionTTLMs: 30 * 60 * 1000 , // 30 minutes
storageKey: 'x-tagging-session' ,
storageTTLMs: 24 * 60 * 60 * 1000 // 24 hours
})
// Session info is automatically included in events
Custom Event Tracking
// Track custom events
store . dispatch ( 'x/tagging/track' , {
event: 'CustomEvent' ,
category: 'user_interaction' ,
action: 'filter_refinement' ,
label: 'price_range' ,
value: { min: 0 , max: 100 },
metadata: {
page: 'search_results' ,
deviceType: 'mobile'
}
})
Consent Management Component
< template >
< div v-if = " showConsentBanner " class = "consent-banner" >
< p > We use cookies and tracking to improve your experience. </ p >
< button @ click = " acceptConsent " > Accept </ button >
< button @ click = " denyConsent " > Decline </ button >
</ div >
</ template >
< script setup lang = "ts" >
import { ref , computed , onMounted } from 'vue'
import { useStore } from 'vuex'
const store = useStore ()
const showConsentBanner = ref ( false )
const consent = computed (() => store . state . x . tagging . consent )
onMounted (() => {
// Show banner if consent not set
if ( consent . value === null ) {
showConsentBanner . value = true
}
})
const acceptConsent = () => {
store . commit ( 'x/tagging/setConsent' , true )
showConsentBanner . value = false
localStorage . setItem ( 'tracking-consent' , 'true' )
}
const denyConsent = () => {
store . commit ( 'x/tagging/setConsent' , false )
showConsentBanner . value = false
localStorage . setItem ( 'tracking-consent' , 'false' )
}
</ script >
Google Analytics
import { watch } from 'vue'
// Forward tagging events to Google Analytics
watch (
() => store . state . x . tagging ,
() => {
// Intercept track action or use event bus
},
{ deep: true }
)
function sendToGA ( event : TaggingEvent ) {
if ( window . gtag ) {
window . gtag ( 'event' , event . event , {
... event ,
send_to: 'GA_MEASUREMENT_ID'
})
}
}
Custom Analytics
import { watch } from 'vue'
import { useStore } from 'vuex'
const store = useStore ()
// Listen to tagging events and forward to your analytics service
store . subscribeAction ({
after : ( action , state ) => {
if ( action . type === 'x/tagging/track' ) {
sendToAnalytics ( action . payload )
}
}
})
async function sendToAnalytics ( event : TaggingEvent ) {
if ( ! store . state . x . tagging . consent ) return
await fetch ( '/api/analytics' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
event ,
sessionId: getSessionId (),
timestamp: Date . now ()
})
})
}
Type Definitions
TaggingRequest
interface TaggingRequest {
url : string
params : Record < string , any >
}
TaggingEvent
interface TaggingEvent {
event : string
[ key : string ] : any
}
Type Reference
Source: /home/daytona/workspace/source/packages/x-components/src/x-modules/tagging/store/module.ts:1
Resources
x-types Tagging type definitions
Tagging Documentation Tagging implementation guide