CampaignLink.astro — UTM Campaign Links
A reusable Astro component for real UTM campaign links: newsletter CTAs, paid/social campaigns, promo banners, partner campaigns, launches, and controlled ad landing URLs.
Good fits
- Email newsletter CTAs
- Paid/social campaign links
- Promo banners
- Partner campaign links
- Launch campaign links
- Controlled ad landing-page URLs
Component
interface Props {
href: string;
utmSource: string;
utmMedium: string;
utmCampaign: string;
utmContent?: string;
utmTerm?: string;
class?: string;
target?: "_self" | "_blank" | "_parent" | "_top";
rel?: string;
ariaLabel?: string;
}
const {
href,
utmSource,
utmMedium,
utmCampaign,
utmContent,
utmTerm,
class: className,
target,
rel,
ariaLabel,
} = Astro.props;
const campaignUrl = new URL(href, Astro.url);
campaignUrl.searchParams.set("utm_source", utmSource);
campaignUrl.searchParams.set("utm_medium", utmMedium);
campaignUrl.searchParams.set("utm_campaign", utmCampaign);
if (utmContent) {
campaignUrl.searchParams.set("utm_content", utmContent);
}
if (utmTerm) {
campaignUrl.searchParams.set("utm_term", utmTerm);
}
const campaignHref = campaignUrl.href;
const externalRel = target === "_blank" ? "noopener noreferrer" : undefined;
const linkRel = rel ?? externalRel;
<a
href={campaignHref}
class:list={className}
target={target}
rel={linkRel}
aria-label={ariaLabel}
>
<slot />
</a>
Examples
Email newsletter CTA
---
import CampaignLink from "@/components/CampaignLink.astro";
---
<CampaignLink
href="/free-consultation/"
utmSource="newsletter"
utmMedium="email"
utmCampaign="may-2026-consultation"
utmContent="main-cta-button"
>
Book a free consultation
</CampaignLink>
Promo banner
---
import CampaignLink from "@/components/CampaignLink.astro";
---
<CampaignLink
href="/offer/"
utmSource="website"
utmMedium="banner"
utmCampaign="spring-sale"
utmContent="homepage-top-banner"
class="promo-banner-link"
>
View the offer
</CampaignLink>
Paid social landing URL
---
import CampaignLink from "@/components/CampaignLink.astro";
---
<CampaignLink
href="https://clientsite.com/dental-implants/"
utmSource="facebook"
utmMedium="paid-social"
utmCampaign="dental-implants-may-2026"
utmContent="before-after-video"
target="_blank"
>
Preview campaign landing page
</CampaignLink>
Prop contract
| Prop | Required | Use |
|---|---|---|
href | Yes | Destination URL. |
utmSource | Yes | Traffic source, such as google, newsletter, facebook, instagram. |
utmMedium | Yes | Channel type, such as cpc, email, paid-social, social, banner. |
utmCampaign | Yes | Campaign or promotion name, such as may-2026-consultation. |
utmContent | No | Creative, CTA, placement, or variant. |
utmTerm | No | Paid search keyword. Use only when relevant. |
class | No | Optional CSS class. |
target | No | Optional anchor target. |
rel | No | Optional custom rel value. |
ariaLabel | No | Optional accessible label. |
Naming rules
Lowercase, hyphen-separated values.
utm_source=facebook
utm_medium=paid-social
utm_campaign=dental-implants-may-2026
utm_content=before-after-video