feat(datasheet): Product-page links carry UTM attribution and report the click
Both Buy renderers (picker hover panel + Part Inspector) now append utm_source=velxio&utm_medium=simulator&utm_campaign=datasheet with the component id in utm_content, so vendors can attribute the referral. trackProductPageClick fires the GA4 event and dispatches a 'velxio:product-page-click' CustomEvent — an overlay build can persist the click server-side without this tree knowing about it.
This commit is contained in:
parent
75842e3668
commit
4b9fa3f0d0
|
|
@ -24,7 +24,8 @@ import { useTranslation } from 'react-i18next';
|
|||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import type { PropertyDescriptor } from '../types/component-metadata';
|
||||
import { loadDoc, type ComponentDoc } from './componentDocs';
|
||||
import { loadDoc, productPageHref, type ComponentDoc } from './componentDocs';
|
||||
import { trackProductPageClick } from '../utils/analytics';
|
||||
import './ComponentInfoPanel.css';
|
||||
|
||||
export interface PanelData {
|
||||
|
|
@ -168,7 +169,13 @@ export const ComponentInfoBody: React.FC<{
|
|||
|
||||
{buyHref && (
|
||||
<div className="cip-footer">
|
||||
<a className="cip-buy" href={buyHref} target="_blank" rel="noopener noreferrer">
|
||||
<a
|
||||
className="cip-buy"
|
||||
href={productPageHref(buyHref, data.id)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={() => trackProductPageClick(data.id, doc?.brand, buyHref)}
|
||||
>
|
||||
<svg
|
||||
width="14"
|
||||
height="14"
|
||||
|
|
|
|||
|
|
@ -56,6 +56,25 @@ export function registerComponentDoc(id: string, raw: string): void {
|
|||
cache.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate a datasheet Buy/Product-page URL with UTM attribution so the
|
||||
* vendor sees the referral came from Velxio. `componentId` lands in
|
||||
* utm_content so partner dashboards can tell WHICH part drove the visit.
|
||||
* Existing query params on the vendor URL are preserved.
|
||||
*/
|
||||
export function productPageHref(url: string, componentId: string): string {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
u.searchParams.set('utm_source', 'velxio');
|
||||
u.searchParams.set('utm_medium', 'simulator');
|
||||
u.searchParams.set('utm_campaign', 'datasheet');
|
||||
u.searchParams.set('utm_content', componentId);
|
||||
return u.toString();
|
||||
} catch {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an optional `---`-delimited front-matter block off the top of a
|
||||
* Markdown string. Only a leading block counts, so table separators
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ import {
|
|||
safeHref,
|
||||
type PanelData,
|
||||
} from '../ComponentInfoPanel';
|
||||
import { productPageHref } from '../componentDocs';
|
||||
import { trackProductPageClick } from '../../utils/analytics';
|
||||
import {
|
||||
layoutInspectorPins,
|
||||
type InspectorPinInput,
|
||||
|
|
@ -813,10 +815,13 @@ export const PartInspectorDialog: React.FC<PartInspectorDialogProps> = ({
|
|||
<div className="pid-actions-right">
|
||||
<a
|
||||
className="pid-buy-button"
|
||||
href={buyHref}
|
||||
href={productPageHref(buyHref, componentMetadata.id)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={buyHref}
|
||||
onClick={() =>
|
||||
trackProductPageClick(componentMetadata.id, doc?.brand, buyHref)
|
||||
}
|
||||
>
|
||||
<svg
|
||||
width="14"
|
||||
|
|
|
|||
|
|
@ -110,6 +110,24 @@ export function trackVisitDiscord(): void {
|
|||
fireEvent('visit_discord', { event_category: 'external_link' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a user clicks a datasheet "Product page" link. Besides the GA4
|
||||
* event, dispatches a DOM CustomEvent so an overlay build can persist the
|
||||
* click server-side (partner attribution) without this tree knowing about it.
|
||||
*/
|
||||
export function trackProductPageClick(componentId: string, brand?: string, href?: string): void {
|
||||
fireEvent('product_page_click', {
|
||||
event_category: 'external_link',
|
||||
component_type: componentId,
|
||||
brand: brand ?? '(none)',
|
||||
});
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('velxio:product-page-click', {
|
||||
detail: { componentId, brand: brand ?? null, href: href ?? null },
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// ── CTA / Conversion ────────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when a user clicks a CTA button on a landing/SEO page. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue