Reported Issue
A Texas hub partner reported that referrals from dp.la appearing in their own site analytics exceed the click-through counts shown in the DPLA Analytics Dashboard. This suggests DPLA is not capturing some portion of outbound clicks to partner sites.
How Click-Throughs Are Currently Tracked
Every "View Full Item" / "View Full Image" / "View Full Text" link on dp.la is given the CSS class clickThrough. A bindLinkEvent utility in dpla-frontend intercepts clicks on these links: it calls event.preventDefault(), fires a Click Through GA4 event via gtag.event(), then opens the partner URL in a new tab via window.open().
This binding happens in two places:
- Item detail page (
/item/[itemId]): bound in componentDidMount in components/ItemComponents/Content/index.js
- Search results, lists, and topic browse pages: bound in a
useEffect in components/shared/ListView/index.js, which fires after React hydration
Identified Gaps
1. Right-click / middle-click bypasses the event listener (most likely cause)
bindLinkEvent only intercepts left-click events via addEventListener("click", ...). It does not intercept:
- Right-click → "Open link in new tab" (most browsers)
- Middle-click (open in background tab)
- Cmd+click / Ctrl+click (Mac/Windows equivalent)
All of these navigate the user to the partner site with Referer: dp.la, so the partner sees a referral — but DPLA never fires a Click Through event. This is the most likely explanation for the discrepancy and is structural: the current tracking architecture cannot capture these interactions.
A fix would require server-side redirect tracking (all external links route through a DPLA endpoint that logs the click, then redirects) or a mousedown listener instead of click, which fires regardless of which button is pressed.
2. Pre-hydration clicks on search results
On the search results page, the clickThrough event listener is bound inside a React useEffect, which runs after client-side hydration. Between when the server-rendered HTML arrives and when the effect fires, the "View Full Item" links are live but unbound — a fast user clicking immediately on page load could follow the link natively, generating a partner referral without a DPLA event.
3. Exhibitions — no click-through tracking
Exhibition pages (/exhibitions/...) track "View Exhibition Item" events when a user navigates to a new item within an exhibition. However, if an exhibition item has an external link to the partner site (a "View at source" style link), there is no Click Through event fired for it. Code search confirms: no clickThrough class, no bindLinkEvent call anywhere in components/ExhibitionsComponents/.
If exhibition pages surface external partner links, those clicks are untracked referrals.
4. Primary Source Sets — unclear
Code search found no clickThrough tracking within components/PrimarySourceSetsComponents/ beyond a sourceUrl prop passed to the CiteButton (used only for citation text). If PSS source item pages or teaching guide pages surface external links to partner content, those are not tracked.
Investigation Needed
-
Quantify the right-click gap: Check if GA4 provides any signal on sessions/users that arrive at partner sites from dp.la vs. what DPLA records as click-throughs. The gap size will indicate whether right-click bypass alone explains the discrepancy.
-
Audit exhibition and PSS pages for untracked external links: Confirm whether any exhibition or PSS page surfaces a "View at source" or equivalent link to a partner URL without a clickThrough binding.
-
Evaluate server-side redirect tracking: Route all clickThrough links through a DPLA redirect endpoint (e.g. /out?url=...) that records the click server-side before redirecting. This would capture right-click, middle-click, and keyboard navigation, and would also allow accurate measurement of whether users actually reach the partner (vs. closing the tab before it loads). Downside: adds latency and a redirect hop.
-
Evaluate mousedown listener: A lower-effort alternative to server-side redirects — binding on mousedown rather than click captures right-click and middle-click without the redirect infrastructure. Does not capture keyboard navigation.
/cc @megannp4
Reported Issue
A Texas hub partner reported that referrals from dp.la appearing in their own site analytics exceed the click-through counts shown in the DPLA Analytics Dashboard. This suggests DPLA is not capturing some portion of outbound clicks to partner sites.
How Click-Throughs Are Currently Tracked
Every "View Full Item" / "View Full Image" / "View Full Text" link on dp.la is given the CSS class
clickThrough. AbindLinkEventutility in dpla-frontend intercepts clicks on these links: it callsevent.preventDefault(), fires aClick ThroughGA4 event viagtag.event(), then opens the partner URL in a new tab viawindow.open().This binding happens in two places:
/item/[itemId]): bound incomponentDidMountincomponents/ItemComponents/Content/index.jsuseEffectincomponents/shared/ListView/index.js, which fires after React hydrationIdentified Gaps
1. Right-click / middle-click bypasses the event listener (most likely cause)
bindLinkEventonly intercepts left-click events viaaddEventListener("click", ...). It does not intercept:All of these navigate the user to the partner site with
Referer: dp.la, so the partner sees a referral — but DPLA never fires aClick Throughevent. This is the most likely explanation for the discrepancy and is structural: the current tracking architecture cannot capture these interactions.A fix would require server-side redirect tracking (all external links route through a DPLA endpoint that logs the click, then redirects) or a
mousedownlistener instead ofclick, which fires regardless of which button is pressed.2. Pre-hydration clicks on search results
On the search results page, the
clickThroughevent listener is bound inside a ReactuseEffect, which runs after client-side hydration. Between when the server-rendered HTML arrives and when the effect fires, the "View Full Item" links are live but unbound — a fast user clicking immediately on page load could follow the link natively, generating a partner referral without a DPLA event.3. Exhibitions — no click-through tracking
Exhibition pages (
/exhibitions/...) track "View Exhibition Item" events when a user navigates to a new item within an exhibition. However, if an exhibition item has an external link to the partner site (a "View at source" style link), there is noClick Throughevent fired for it. Code search confirms: noclickThroughclass, nobindLinkEventcall anywhere incomponents/ExhibitionsComponents/.If exhibition pages surface external partner links, those clicks are untracked referrals.
4. Primary Source Sets — unclear
Code search found no
clickThroughtracking withincomponents/PrimarySourceSetsComponents/beyond asourceUrlprop passed to theCiteButton(used only for citation text). If PSS source item pages or teaching guide pages surface external links to partner content, those are not tracked.Investigation Needed
Quantify the right-click gap: Check if GA4 provides any signal on sessions/users that arrive at partner sites from dp.la vs. what DPLA records as click-throughs. The gap size will indicate whether right-click bypass alone explains the discrepancy.
Audit exhibition and PSS pages for untracked external links: Confirm whether any exhibition or PSS page surfaces a "View at source" or equivalent link to a partner URL without a
clickThroughbinding.Evaluate server-side redirect tracking: Route all
clickThroughlinks through a DPLA redirect endpoint (e.g./out?url=...) that records the click server-side before redirecting. This would capture right-click, middle-click, and keyboard navigation, and would also allow accurate measurement of whether users actually reach the partner (vs. closing the tab before it loads). Downside: adds latency and a redirect hop.Evaluate
mousedownlistener: A lower-effort alternative to server-side redirects — binding onmousedownrather thanclickcaptures right-click and middle-click without the redirect infrastructure. Does not capture keyboard navigation./cc @megannp4