Personal Website for @jaspermayone.com
jaspermayone.com
1"use client";
2
3import {
4 useCallback,
5 MouseEvent,
6 ReactNode,
7 AnchorHTMLAttributes,
8} from "react";
9
10interface ExternalLinkProps extends Omit<
11 AnchorHTMLAttributes<HTMLAnchorElement>,
12 "href" | "target" | "rel"
13> {
14 href: string;
15 children: ReactNode;
16}
17
18/**
19 * External link component that adds UTM params on click.
20 * Shows clean URL on hover, but navigates with tracking params.
21 */
22export function ExternalLink({
23 href,
24 children,
25 onClick,
26 ...props
27}: ExternalLinkProps) {
28 const handleClick = useCallback(
29 (e: MouseEvent<HTMLAnchorElement>) => {
30 e.preventDefault();
31
32 // Call any passed onClick handler
33 onClick?.(e);
34
35 // Add UTM params
36 const url = new URL(href);
37 url.searchParams.set("utm_source", "jaspermayone.com");
38 url.searchParams.set("utm_medium", "referral");
39
40 window.open(url.toString(), "_blank", "noopener,noreferrer");
41 },
42 [href, onClick]
43 );
44
45 return (
46 <a
47 href={href}
48 onClick={handleClick}
49 target="_blank"
50 rel="noopener noreferrer"
51 {...props}
52 >
53 {children}
54 </a>
55 );
56}
57
58export default ExternalLink;