3737
3838// Parse a "Category, Action, Name" attribute string and push a trackEvent call
3939// to the Matomo queue. Name is optional; returns early if fewer than 2 parts.
40- function pushMatomoEvent ( raw ) {
40+ // `context` is the DOM element that triggered the event; it is forwarded to
41+ // every helper so functions like getElementText can reference it.
42+ function pushMatomoEvent ( raw , context ) {
4143
4244 // Split on commas, trim whitespace from each part, drop any empty strings.
4345 const parts = ( raw || "" ) . split ( "," ) . map ( ( s ) => s . trim ( ) ) . filter ( Boolean ) ;
@@ -46,12 +48,14 @@ function pushMatomoEvent(raw) {
4648
4749 // Resolve any {{functionName}} tokens by calling the matching helper.
4850 // Each token is replaced in-place, so it can appear anywhere in a segment.
51+ // The context element is passed as the first argument so helpers can
52+ // inspect the element that triggered the event (e.g. getElementText).
4953 const helpers = window . MatomoHelpers || { } ;
5054 const resolved = parts . map ( ( part ) =>
5155 part . replace ( / \{ \{ ( \w + ) \} \} / g, ( _ , fnName ) => {
5256 const fn = helpers [ fnName ] ;
5357 // Call the function if it exists; otherwise leave the token as-is.
54- return ( typeof fn === "function" ) ? fn ( ) : `{{${ fnName } }}` ;
58+ return ( typeof fn === "function" ) ? fn ( context ) : `{{${ fnName } }}` ;
5559 } )
5660 ) ;
5761
@@ -91,7 +95,9 @@ document.addEventListener("click", (event) => {
9195 // (guards against the unlikely case where closest() finds an ancestor of el).
9296 if ( ! el . contains ( interactive ) && el !== interactive ) return ;
9397
94- pushMatomoEvent ( el . dataset . matomoClick ) ;
98+ // Pass the interactive element as context so helpers like getElementText
99+ // can read the text of the specific link or button that was clicked.
100+ pushMatomoEvent ( el . dataset . matomoClick , interactive ) ;
95101} ) ;
96102
97103// ---------------------------------------------------------------------------
@@ -113,22 +119,22 @@ function trackIfSeen(el) {
113119 // Check the element itself for the attribute.
114120 if ( el . dataset . matomoSeen ) {
115121 seenTracked . add ( el ) ;
116- pushMatomoEvent ( el . dataset . matomoSeen ) ;
122+ pushMatomoEvent ( el . dataset . matomoSeen , el ) ;
117123 }
118124
119125 // Also check any descendants — content loaders often inject a whole subtree
120126 // at once, so walking deep ensures every marked element is captured.
121127 el . querySelectorAll ( "[data-matomo-seen]" ) . forEach ( ( child ) => {
122128 if ( seenTracked . has ( child ) ) return ;
123129 seenTracked . add ( child ) ;
124- pushMatomoEvent ( child . dataset . matomoSeen ) ;
130+ pushMatomoEvent ( child . dataset . matomoSeen , child ) ;
125131 } ) ;
126132}
127133
128134// Process all elements already present in the DOM on initial page load.
129135document . querySelectorAll ( "[data-matomo-seen]" ) . forEach ( ( el ) => {
130136 seenTracked . add ( el ) ;
131- pushMatomoEvent ( el . dataset . matomoSeen ) ;
137+ pushMatomoEvent ( el . dataset . matomoSeen , el ) ;
132138} ) ;
133139
134140// Watch for any new nodes added to the DOM after initial load.
@@ -154,7 +160,7 @@ document.addEventListener("turbo:load", () => {
154160 document . querySelectorAll ( "[data-matomo-seen]" ) . forEach ( ( el ) => {
155161 if ( seenTracked . has ( el ) ) return ;
156162 seenTracked . add ( el ) ;
157- pushMatomoEvent ( el . dataset . matomoSeen ) ;
163+ pushMatomoEvent ( el . dataset . matomoSeen , el ) ;
158164 } ) ;
159165
160166 // Re-attach the observer to the new document.body instance.
@@ -184,11 +190,23 @@ function getActiveTabName() {
184190 return activeAnchor . textContent . trim ( ) ;
185191}
186192
193+ // ---------------------------------------------------------------------------
194+ // Get the visible text of the element that triggered the event.
195+ // For click tracking this is the interactive element (link, button, etc.).
196+ // For seen tracking this is the element carrying data-matomo-seen.
197+ // Returns an empty string if no context element is available.
198+ // ---------------------------------------------------------------------------
199+ function getElementText ( el ) {
200+ if ( ! el ) return "" ;
201+ return el . textContent . trim ( ) ;
202+ }
203+
187204// ---------------------------------------------------------------------------
188205// Register helpers on window.MatomoHelpers so they can be referenced with the
189206// {{functionName}} syntax in data-matomo-seen and data-matomo-click attributes.
190207// Add new helpers here as needed.
191208// ---------------------------------------------------------------------------
192209window . MatomoHelpers = {
193210 getActiveTabName,
211+ getElementText,
194212} ;
0 commit comments