nuxt-x-affiliate
nuxt-x-affiliate
The everything-layer for niche affiliate review sites. 99 XAF* components under the same prefix (10 dashboard family + 89 review-site family), schema.org JSON-LD composables (Product, Review, FAQ, Breadcrumb, Organization, Person, WebSite, Article, HowTo, Recipe), FTC + opt-in legal disclosures, GTM click + impression tracking, site chrome + engagement loops + conversion widgets, and a full merchant tagging API. A consuming site provides the data; every block on the page is wired.
Breaking (next minor after v0.6.0, 2026-07): the dashboard family moved from
app/components/X/AF/toapp/components/XAF/— all 99 components now live flat in one folder. Auto-import names (XAFBanner,XAFDashboard, …) are unchanged, so template usage is unaffected. Only consumers deep-importing component file paths (e.g.import XAFDashboard from '@xenterprises/nuxt-x-affiliate/app/components/X/AF/Dashboard.vue') need to update the path toapp/components/XAF/Dashboard.vue.Also breaking (same minor):
useConsentTracking()is renamed touseXAFConsentTracking()(pluginconsent-tracking.client.ts→xaf-consent-tracking.client.ts) to resolve the auto-import collision withnuxt-x-marketing's identically-named composable when a site extends both layers. Behavior, thexAffiliate.consentstorage key, and thexAffiliate.trackingconfig are unchanged — update call sites to the new name.
Latest (v0.6.0, 2026-06-29):
<XAFContentCard>and<XAFPageHero>ship first-class image support (image/imageAlt/imageAspect/imageLoadingprops) — no more per-site forks for card thumbnails and photo heroes. No breaking changes. Full release notes →
Previous (v0.5.0, 2026-06-28): Consent-aware cookie banner rewritten on Nuxt UI v4 primitives (
UModal,UToggle,UButton,UBadge) with banner + preferences modal in one. NewuseConsentTracking()composable dynamically injects GTM / GA4 / Clarity / Meta Pixel / Hotjar / custom scripts only after the matching consent category is granted. Storage moved cookie → localStorage to align withnuxt-x-marketing. NewxAffiliate.tracking.scripts[]escape hatch. 181/181 tests, 0 typecheck errors. No breaking changes. Full release notes →
Previous (v0.4.1, 2026-06-28): Multi-language support out of the box. New
<XAFLocaleProvider>(cookie persistence + window event +<html lang>/dir+ optional built-in switcher) +useXafLocale()composable. Default 9-locale list (en, es, fr, de, pt, it, ja, zh, ar) with RTL support. 159/159 tests, 0 typecheck errors. No breaking changes.
Previous (v0.3.5, 2026-06-28): 5 new components (
<XAFPagination>,<XAFSearchFilters>,<XAFTaxonomyArchive>,<XAFCurrencySwitcher>,<XAFPageHero>,<XAFPageSection>) + 1 composable (useXafExperiment()). Typecheck gate enforced in CI andprepublishOnly. 47 pre-existing strict-mode typecheck errors swept. Nuxt 4 config plumbing fixes (multi-export composables, defu-merge-safe defaults). 89 components total (78 → 89).
Two component families under the same package, both flat in app/components/XAF/:
XAF*dashboard family (10 components) — for running your own affiliate program.XAF*review-site family (89 components) — for being an affiliate of networks like Amazon and Walmart. Covers every block from a product hero through FAQ through sticky CTA through decision quiz, plus site chrome (header/footer/mega menu/404) and engagement loops (polls/quizzes/comments), pagination, faceted filters, taxonomy archives, currency switching, and A/B testing hooks. Auto-imported; plug-and-play.
Installation
npm install @xenterprises/nuxt-x-affiliate
Peer requirements: nuxt ^4.2.1 and @nuxt/ui ^4.9.0.
// nuxt.config.ts
export default defineNuxtConfig({
extends: [['@xenterprises/nuxt-x-affiliate', { install: true }]],
})
What the consumer writes
The batteries are included — the layer ships default pages (/affiliate, /affiliate/dashboard), 99 auto-imported components, and every composable. The ideal consumer writes three things:
extendsinnuxt.config.ts(above).app/app.config.ts— it must live in the consuming project'sapp/directory (Nuxt 4srcDirconvention); at the project root your overrides are silently ignored and only Nuxt UI defaults survive. Site identity, legal base URL, tracking IDs, and merchant tags:
// app/app.config.ts
export default defineAppConfig({
xAffiliate: {
// Canonical legal pages live centrally — every site points here.
legal: {
baseUrl: 'https://x.enterprises/legal',
optIn: {
health: false, // → enables <XAFHealthDisclaimer>
aiContent: true, // → enables <XAFAIContentDisclosure>
sponsoredContent: false, // → enables <XAFSponsoredContentDisclosure>
},
},
brand: {
name: 'BestKitchenGear.com', // required — layer default is undefined
url: 'https://bestkitchengear.com', // required — layer default is undefined
tagline: 'We test so you don\'t have to.',
logo: 'https://bestkitchengear.com/logo.png',
ogImage: 'https://bestkitchengear.com/og.png',
},
author: {
name: 'Jane Reviewer', // E-E-A-T — drives <XAFAuthorBox> + Person schema
role: 'Senior Kitchen Gear Editor',
},
tracking: {
gtmId: 'GTM-XXXXXXX', // scripts fire only after consent (via <XAFCookieConsent>)
},
},
xAffiliateContent: {
merchants: {
// Sites MUST set their own tag per merchant — untagged links
// silently break commission attribution.
amazon: { tagValue: 'yourtag-20' },
walmart: { tagValue: 'your-walmart-id' },
},
},
})
- Environment variables — none. This layer reads no env vars; all configuration is through
app/app.config.ts.
Everything else is opt-out or override: drop <XAF*> components into your pages, call the schema composables per page, and replace any default page via Nuxt's standard page overriding (your file at the same path wins) — or disable a default page entirely via the xAffiliate.pages switches (the route then renders a 404):
export default defineAppConfig({
xAffiliate: {
pages: {
landing: true, // /affiliate
dashboard: false, // /affiliate/dashboard → 404
},
},
})
The layer ships no default homepage — review sites compose their own from the XAF* family (XAFHero, XAFContentIndex, …). Dashboard-family defaults (landing hero, benefits, signup strings) can be overridden under the same xAffiliate namespace:
export default defineAppConfig({
xAffiliate: {
referralParam: 'ref',
referralBaseUrl: 'https://yoursite.com',
cookieDays: 30,
currency: 'USD',
shareMessage: 'Check this out!',
},
})
What the Layer Provides
Dashboard family (XAF*)
Components (auto-imported):
XAFBanner— Promotional hero banner with CTA and variant styling (gradient / primary / dark)XAFCommissionTiers— Commission tier display with current-tier highlight and progress barXAFDashboard— Full affiliate dashboard composing all sub-componentsXAFLeaderboard— Top affiliates ranking with earnings and referral countsXAFPayoutHistory— Payout history table with status badgesXAFReferralLink— Referral link with copy-to-clipboardXAFReferralTable— Referral tracking table (source, status, commission, date)XAFShareButtons— Social sharing buttons (Twitter, Facebook, LinkedIn, Email)XAFSignupForm— Affiliate application form with configurable fieldsXAFStatsCards— Stats overview cards (clicks, conversions, earnings, pending)
Review-site family (XAF*) — 89 components
SEO + E-E-A-T:
XAFBreadcrumbs— BreadcrumbList schema, accessible navXAFAuthorBox— Author bio with credentials + social (E-E-A-T)XAFContributors— Multi-author byline (tester + writer + editor + photographer)XAFByline— Minimal byline ("By Jane, Tom, and Sam") with dates + read timeXAFVerdict— TL;DR / verdict callout (featured-snippet gold)XAFFAQ— FAQ list + FAQPage schemaXAFLastUpdated— "Updated {date}" freshness badgeXAFReadingTime— "{n} min read" badge (auto-computed from content)XAFPriceVerified— "Price verified {date}" trust badgeXAFPressLogos— "As seen in" media logos (E-E-A-T)XAFExpertQuote— Quoted experts with credentials + link
Data / structured content:
XAFSpecsTable— Spec sheet with optional groupingXAFComparisonTable— vs-competitors with "Our pick" highlightXAFScoreBreakdown— Sub-scores with weighted average + totalXAFDecisionMatrix— Multi-criteria weighted scoring matrixXAFCalloutBox— info / success / warning / danger / tipXAFQuote— Pull-quote with optional sourceXAFKeyTakeaways— Bulleted key-points listXAFTableOfContents— Auto-generated from article headings, scrollspy active highlightXAFMethodology— "How we test" editorial disclosureXAFSurveyResults— Survey data with bar visualizationXAFCustomerReviews— User-submitted reviews with rating distributionXAFStatHighlight— Big-number statistic card with optional icon, context, and trend
Commerce:
XAFHero— Product hero (image + title + rating + price + CTA)XAFProductCard— Product card for gridsXAFReviewCard— Review summary card for listsXAFStickyCTA— Floating buy button appears when original scrolls outXAFStarRating— Half-star ratings, 4 color variantsXAFBuyButton— The moneymaker — image, price, CTA, disclosure, tagging, click + impression trackingXAFAffiliateLink— Slot-based link when you need full visual controlXAFProsCons— 1- or 2-column pros/cons, auto-collapseXAFBestFor— "Best for X" badge (3 variants)XAFDealAlert— Email-me-when-price-drops signupXAFWaitlist— Email-me-when-back-in-stock signupXAFBundle— Bundle of two or more products with savings label and totalXAFCountdown— Live countdown timer for limited-time offers with auto-expiry handlingXAFOfferBanner— Dismissible site-wide promo / info / warning / success bannerXAFShippingBar— Free-shipping progress bar ("Add $X more to qualify")
Legal:
XAFDisclosure— FTC disclosure in 4 variantsXAFArticleDisclosure— FTC 16 CFR §255.5 in-content snippetXAFAIContentDisclosure— AI-assisted content notice (opt-in vialegal.optIn.aiContent)XAFSponsoredContentDisclosure— Paid sponsorship notice (opt-in vialegal.optIn.sponsoredContent)XAFHealthDisclaimer— Not-medical-advice notice (opt-in vialegal.optIn.health)XAFCookieConsent— Consent-aware GDPR / CCPA banner with category-level preferences + auto-tracking injection (GTM / GA4 / Clarity / Meta Pixel / Hotjar / etc.) fromxAffiliate.tracking
Social / growth:
XAFNewsletter— Email capture withsubmitevent + privacy linkXAFExitIntent— Exit-intent popup with email capture + cookie dismissalXAFSocialProof— "Trending", "Bought today" signalsXAFTestimonials— Reader testimonial gridXAFShareReview— Share to Twitter / FB / LinkedIn / Reddit / WhatsApp / Email / Copy linkXAFPrintButton— Print-friendly exportXAFReactions— "Helpful / Not helpful" buttonsXAFSearchBar— Site search with combobox + keyboard navXAFNewsletterArchive— Past newsletter issues list (date, subject, excerpt, product count)XAFRssFeedLink— Head-only RSS auto-discovery<link>tag (renders nothing visible)
Reader engagement / page chrome:
XAFReadingProgress— Top progress bar with reading % ARIAXAFBackToTop— Floating back-to-top button (appears after scroll threshold)XAFQuickActions— Floating side menu (save / share / copy / print / report)XAFTagChips— Clickable tag chips at end of articleXAFContentCard— Review or article card with meta, optional rating, price line, and CTAXAFAskQuestion— Reader-submitted question form with optional emailXAFCommentForm— Comment form with optional email and threaded repliesXAFCommentList— Threaded comment list with reply / upvote actionsXAFPoll— Single-question poll with optional pre-vote resultsXAFQuiz— Multi-step product recommendation quiz with progress barXAFDecisionFlow— Interactive flowchart quiz that lands on a recommended productXAFNotFound— Friendly 404 page (or any status code) with status code, CTA, and inline searchXAFPageHero— Full-viewport hero for landing / category pages with eyebrow, title, actions slotXAFPageSection— Bounded-width section wrapper with bg / padding / id propsXAFContentIndex— Listing-page section composingXAFContentCardgrids/lists with hero header, empty state, and "View all" linkXAFDateDisplay— Locale-aware<time>element for ISO dates (long / short / numeric / relative presets, UTC-pinned for SSR)
Schema-specific:
XAFHowTo— HowTo schema + numbered steps UIXAFRecipe— Recipe schema + recipe card with ingredients + nutrition
Media:
XAFVideoEmbed— YouTube / Vimeo embedXAFGallery— Image gallery (grid / carousel / masonry) + optional lightboxXAFRelatedProducts— "You might also like" sectionXAFCompareSlider— Before/after image compare slider (horizontal / vertical)
Composables:
useAffiliate()— SSR-safe state for affiliate program datauseReferralTracking()— Detects and persists referral codes via URL params and cookiesuseAffiliateContent()— Review-site API: merchant config, idempotent link tagging, price formatting, click trackinguseAffiliateImpression()/trackImpression()— IntersectionObserver-based impression tracking (firesaffiliate_impressionto dataLayer when buy button enters viewport)useSchema()— Multi-export schema.org JSON-LD composable:useOrganizationSchema()— site-wide OrganizationusePersonSchema()— author Person (E-E-A-T)useProductSchema()— Product + Review + AggregateRating + Offer (drives Google star SERPs)useFAQSchema()— FAQPageuseBreadcrumbSchema()— BreadcrumbListuseWebSiteSchema()— WebSite + optional SearchAction (sitelinks searchbox)useArticleSchema()— Article with publisheruseSiteMeta()— title / description / OG / Twitter Card / canonical / robotscleanSchema()— strips undefined/empty values
useXAFConsentTracking()— Consent-aware script injection (GTM / GA4 / Clarity / custom) gated on<XAFCookieConsent>categoriesuseXafLocale()— Multi-locale state (cookie persistence,<html lang>/dir, RTL support) behind<XAFLocaleProvider>useXafExperiment()— Sticky A/B test variant assignment with exposure trackinguseXAFContentQuery()— Paginated content query state manager, plus typed wrappersuseXAFReviews()/useXAFArticles()/useXAFCategories()/useXAFSearch()useXafDateFormat()— Locale-aware date formatting (long / short / numeric / relative presets, UTC pinning for SSR)useXafRssFeed()— RSS 2.0 XML generation with channel defaults fromxAffiliate.branduseXAFStructuredData()— Multi-export JSON-LD composable:useXAFVideoSchema(),useXAFHowToSchema(),useXAFItemListSchema(),useXAFSoftwareApplicationSchema(),useXAFRecipeSchema()
Pages:
/affiliate— Public landing page with hero, benefits, commission tiers, and signup form (disable viaxAffiliate.pages.landing: false)/affiliate/dashboard— Affiliate dashboard with full metrics and tools; shows a sign-in prompt untiluseAffiliate()state is populated (disable viaxAffiliate.pages.dashboard: false)
Server routes:
GET /api/rss— Generic RSS 2.0 feed (empty item list); override with your ownserver/api/rss.get.tsto feed real content. SeeBACKEND-REQUIREMENTS.mdin the package for the full (minimal) server contract.
App Config Options
The layer exposes two config namespaces — site-wide (xAffiliate covers dashboard + brand + author + legal + tracking) and content (xAffiliateContent covers merchants).
xAffiliate.pages — default-page opt-outs
export default defineAppConfig({
xAffiliate: {
pages: {
landing: true, // /affiliate — set false to 404 the route
dashboard: true, // /affiliate/dashboard — set false to 404 the route
},
},
})
xAffiliate.legal — canonical legal pages + opt-in disclosures
export default defineAppConfig({
xAffiliate: {
legal: {
baseUrl: 'https://x.enterprises/legal',
optIn: {
health: false, // → enables <XAFHealthDisclaimer>
aiContent: false, // → enables <XAFAIContentDisclosure>
sponsoredContent: false, // → enables <XAFSponsoredContentDisclosure>
},
},
},
})
xAffiliate.author — site author identity (E-E-A-T)
export default defineAppConfig({
xAffiliate: {
author: {
name: 'Jane Reviewer',
role: 'Senior Kitchen Gear Editor',
bio: '8 years reviewing kitchen equipment for home cooks.',
image: '/team/jane.jpg',
credentials: ['CNC-certified reviewer', '8 years testing kitchen gear'],
social: {
twitter: 'https://twitter.com/jane',
linkedin: 'https://linkedin.com/in/jane',
website: 'https://janereviews.com',
},
},
},
})
xAffiliate.brand — site brand identity
export default defineAppConfig({
xAffiliate: {
brand: {
name: 'BestKitchenGear.com',
tagline: 'We test so you don\'t have to.',
logo: 'https://bestkitchengear.com/logo.png',
url: 'https://bestkitchengear.com',
ogImage: 'https://bestkitchengear.com/og.png',
twitter: 'bestkitchengear',
ogType: 'website',
locale: 'en_US',
},
},
})
xAffiliate.tracking — GTM / GA4 / Clarity
export default defineAppConfig({
xAffiliate: {
tracking: {
gtmId: 'GTM-XXXXXXX',
ga4Id: 'G-XXXXXXXX',
clarityId: 'abc123def4',
autoInject: true,
},
},
})
xAffiliateContent — merchant tagging + currency
export default defineAppConfig({
xAffiliateContent: {
currency: 'USD',
locale: 'en-US',
disclosure: {
text: 'Affiliate link. We may earn a commission at no cost to you.',
position: 'above',
},
merchants: {
amazon: { tagValue: 'yourtag-20' },
walmart: { tagValue: 'TODO' },
},
},
})
Minimal Usage Example
<script setup>
const { affiliate, stats, referralUrl, setAffiliate, setStats } = useAffiliate()
// Your app fetches data and populates state
onMounted(async () => {
const data = await $fetch('/api/affiliate/me')
setAffiliate(data.affiliate)
setStats(data.stats)
})
</script>
<template>
<XAFDashboard />
</template>
Component Props Reference
XAFBanner
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | required | Banner headline text |
description | string | — | Subtitle text |
ctaLabel | string | 'Join Now' | CTA button label |
ctaTo | string | '/affiliate' | CTA link destination |
ctaColor | string | 'white' | CTA button color |
highlightText | string | — | Highlight badge text |
variant | 'primary' | 'gradient' | 'dark' | 'gradient' | Visual style |
showDecoration | boolean | true | Show background decoration |
XAFSignupForm
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | 'Join Our Affiliate Program' | Form title |
subtitle | string | 'Earn commissions...' | Form subtitle |
submitLabel | string | 'Apply Now' | Submit button label |
successMessage | string | 'Application submitted...' | Success message after submit |
showWebsite | boolean | true | Show website URL field |
showCompany | boolean | false | Show company name field |
showMessage | boolean | true | Show promotion strategy textarea |
Emits: submit(data: AffiliateFormData)
XAFStatsCards
| Prop | Type | Default | Description |
|---|---|---|---|
stats | AffiliateStats | null | required | Stats data object |
currency | string | 'USD' | Currency code for formatting |
XAFReferralLink
| Prop | Type | Default | Description |
|---|---|---|---|
affiliate | Affiliate | null | required | Current affiliate data |
referralUrl | string | required | Full referral URL to display and copy |
XAFCommissionTiers
| Prop | Type | Default | Description |
|---|---|---|---|
tiers | CommissionTier[] | required | Array of commission tier definitions |
currentTierId | string | null | null | ID of the affiliate's current tier |
nextTier | CommissionTier | null | null | Next tier to reach |
progressToNextTier | number | 0 | Progress percentage (0–100) |
XAFLeaderboard
| Prop | Type | Default | Description |
|---|---|---|---|
entries | { name, referrals, earnings }[] | required | Leaderboard entries |
title | string | 'Top Affiliates' | Section title |
period | string | 'This Month' | Time period badge |
currency | string | 'USD' | Currency code |
Review-site family props
XAFStarRating
| Prop | Type | Default | Description |
|---|---|---|---|
rating | number | required | 0 to max. Decimals supported for half-stars. Values outside range are clamped. |
max | number | 5 | Number of stars. |
variant | 'inline' | 'hero' | 'inline' | Visual size. |
showNumber | boolean | true | Show numeric value next to stars. |
showScale | boolean | false | Show " / 5" suffix. |
color | 'amber' | 'primary' | 'success' | 'warning' | 'amber' | Filled-star color. |
Renders with role="img" and a proper aria-label (e.g. "Rated 4.3 out of 5 stars").
XAFBuyButton
The moneymaker — image, price, CTA, disclosure, tagging, and click tracking in one component.
| Prop | Type | Default | Description |
|---|---|---|---|
link | AffiliateLink | — | Full link object (recommended for MDC). |
merchant | MerchantId | 'amazon' | Merchant when not passing link. |
url | string | '#' | Outbound URL when not passing link. |
price | number | — | Price for display + currency formatting. |
image | string | — | Product image URL. |
productName | string | — | Alt text + headline. |
label | string | — | Sub-headline. |
compact | boolean | false | Compact horizontal layout. |
ctaLabel | string | from merchant | Override the merchant-default CTA label. |
color | 'primary' | 'success' | 'neutral' | 'primary' | Button color. |
newTab | boolean | true | Open in a new tab. |
disabled | boolean | false | Render as a disabled link. |
showDisclosure | boolean | true | Show the FTC disclosure text. |
position | string | — | Position label for click tracking (e.g. 'hero', 'sidebar'). |
Emits: click with { url, merchant, originalUrl }. Pushes affiliate_click to window.dataLayer if GTM / GA4 is loaded (noop otherwise). Renders with rel="sponsored noopener noreferrer" on the anchor for FTC compliance.
XAFAffiliateLink
Slot-based link when you need full visual control over the CTA.
| Prop | Type | Default | Description |
|---|---|---|---|
merchant | MerchantId | required | Merchant to tag for. |
url | string | required | Outbound URL. |
to | string | — | Render as <NuxtLink> if internal route. |
disabled | boolean | false | Render as a non-interactive span. |
newTab | boolean | true | Open in a new tab. |
Slot props: { merchant, merchantId, tagged } — merchant is the resolved merchant config, tagged is a boolean indicating whether the URL already carries a tag.
Emits: click { url, merchant, originalUrl } and navigate { url }.
XAFProsCons
| Prop | Type | Default | Description |
|---|---|---|---|
pros | string[] | [] | List of pros. |
cons | string[] | [] | List of cons. |
columns | 1 | 2 | 2 | Number of columns. Auto-collapses to 1 if only one side has content. |
prosLabel | string | 'What we like' | Header for the pros section. |
consLabel | string | "What we don't" | Header for the cons section. |
Renders an empty-state message when both pros and cons are empty.
XAFDisclosure
FTC disclosure text in 4 visual variants.
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | from config | Override the disclosure text. |
variant | 'inline' | 'compact' | 'footer' | 'banner' | 'inline' | Visual variant. |
as | string | chosen by variant | Override the HTML tag. |
showIcon | boolean | true for inline/compact | Show the icon. |
XAFArticleDisclosure
In-content FTC 16 CFR §255.5 snippet — sits at the top of every review / article page in-flow with the article typography.
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | from config | Override the disclosure body text. |
link | string | 'https://x.enterprises/legal/affiliate-disclosure' | Override the link URL. |
linkLabel | string | 'Read our full disclosure policy' | Override the link label. |
publishedAt | string (ISO YYYY-MM-DD) | — | First-published date. |
updatedAt | string (ISO YYYY-MM-DD) | — | Last-updated date. Only shown if it differs from publishedAt. |
locale | string | 'en-US' | Locale for date formatting. Dates are UTC-pinned for SSR stability. |
Renders with role="note" and aria-label="Affiliate disclosure".
Composables
useAffiliate()
SSR-safe state management using Nuxt useState. The consuming app calls setters after fetching data from its API.
const {
config, // Reactive app config for xAffiliate
affiliate, // Affiliate | null
stats, // AffiliateStats | null
referrals, // Referral[]
payouts, // Payout[]
tiers, // CommissionTier[]
isLoading, // boolean
error, // string | null
isAuthenticated, // computed — whether affiliate is set
isActive, // computed — whether status is 'active'
referralUrl, // computed — full referral URL with code
currentTier, // computed — current CommissionTier
nextTier, // computed — next CommissionTier
progressToNextTier, // computed — progress % to next tier
setAffiliate,
setStats,
setReferrals,
setPayouts,
setTiers,
reset,
} = useAffiliate()
useReferralTracking()
Detects referral codes from URL query parameters and persists them in cookies. SSR-safe — cookie operations are guarded by import.meta.server checks.
const {
referralCode, // string | null
referralSource, // string | null (UTM source)
detectReferral, // () => void — detect from URL params or cookie
clearReferral, // () => void
hasReferral, // () => boolean
getReferralCode, // () => string | null
} = useReferralTracking()
useAffiliateContent()
Review-site API: merchant config, idempotent link tagging, price formatting, and click tracking.
const {
config, // Resolved XAffiliateContentConfig
getMerchant, // (id: MerchantId) => XAffiliateContentMerchant
hasTag, // (id: MerchantId) => boolean — true if merchant has tagValue set
taggedUrl, // (merchant, url) => string — appends tag, idempotent
taggedLink, // (link: AffiliateLink) => AffiliateLink
formatPrice, // (amount: number) => string — Intl currency
trackClick, // (payload) => void — pushes affiliate_click to dataLayer
} = useAffiliateContent()
taggedUrl(merchant, url)— appends the configured tag param. Idempotent: re-running on an already-tagged URL returns it unchanged.formatPrice(amount)—Intl.NumberFormatwith the configured currency / locale.getMerchant(id)/hasTag(id)— display metadata + tag presence checks.trackClick({ url, merchant, position, originalUrl })— firesaffiliate_clicktowindow.dataLayerwhen GTM is loaded (noop otherwise).
Schema.org JSON-LD
Drive Google star SERPs, FAQ rich results, breadcrumb SERPs, and the Knowledge Panel with one composable per schema type. Each composable injects a <script type="application/ld+json"> block into the page head automatically.
// In a review page's <script setup>:
useProductSchema({
product: {
name: 'Wireless Keyboard K1',
description: 'Compact mechanical keyboard with hot-swappable switches',
image: 'https://cdn.example.com/k1.jpg',
brand: 'Logitech',
},
ratingValue: 4.6,
ratingCount: 1234,
offer: { price: 79.99, priceCurrency: 'USD', availability: 'InStock' },
datePublished: '2026-01-15',
reviewBody: 'After 3 months of daily use...',
})
useFAQSchema({
faqs: [
{ question: 'Is it waterproof?', answer: 'Yes, IPX7 rated.' },
{ question: 'Battery life?', answer: '20 hours with backlight off.' },
],
})
useBreadcrumbSchema({
items: [
{ label: 'Home', href: '/' },
{ label: 'Reviews', href: '/reviews' },
{ label: 'Wireless Keyboards' },
],
})
useSiteMeta({
title: 'Logitech K1 Review: Best Wireless Keyboard of 2026',
description: 'We tested 12 wireless keyboards. The K1 wins on feel, battery, and price.',
image: 'https://cdn.example.com/k1-hero.jpg',
type: 'article',
publishedTime: '2026-01-15',
author: 'Jane Reviewer',
})
For site-wide setup (call once in app.vue or a layout):
useOrganizationSchema()
usePersonSchema() // uses xAffiliate.author
useWebSiteSchema({ searchUrlTemplate: 'https://example.com/search?q={search_term_string}' })
Environment Variables
This layer reads no environment variables directly. All configuration is through app.config.ts.
Layer Architecture
| Path | Purpose |
|---|---|
nuxt.config.ts | Registers @nuxt/ui module and Tailwind CSS |
app/app.config.ts | All configurable options under xAffiliate (dashboard + brand + author + legal + tracking) and xAffiliateContent (merchants) namespaces with TypeScript type augmentation |
app/app.vue | Root component for the layer |
app/composables/ | useAffiliate, useReferralTracking, useAffiliateContent, useAffiliateImpression, useSchema (multi-export), useXAFConsentTracking, useXafLocale, useXafExperiment, useXAFContentQuery, useXafDateFormat, useXafRssFeed, useXAFStructuredData (multi-export) |
app/components/XAF/ | 99 auto-imported components, flat — 10 dashboard-family + 89 review-site-family (FTC-compliant, schema-aware, GTM-tracked), all built on Nuxt UI v4 |
app/pages/ | /affiliate (landing), /affiliate/dashboard (authenticated) — both opt-out-able via xAffiliate.pages.* |
server/api/ | rss.get.ts — generic RSS 2.0 feed endpoint (empty item list; override in the consumer) |
app/types/ | TypeScript interfaces for Affiliate program, Schema.org shapes, and component prop types |
AI Context
package: "@xenterprises/nuxt-x-affiliate"
version: "0.6.0"
use-when: >
Building a niche affiliate review site on Nuxt 4. v0.6.0 is the
everything-layer — 99 XAF components + a dozen composable modules
covering every block on a review page. A consuming site provides
data; every block is wired.
Two component families share the XAF prefix and are auto-imported,
both flat in app/components/XAF/:
(1) Dashboard family (XAF/*.vue) — 10 components for running your own
affiliate program (signup forms, referral links, commission tiers,
stats, authenticated dashboard).
(2) Review-site family (XAF/*.vue) — 89 components covering:
- SEO + E-E-A-T: XAFBreadcrumbs, XAFAuthorBox, XAFContributors,
XAFByline, XAFVerdict, XAFFAQ, XAFLastUpdated, XAFReadingTime,
XAFPriceVerified, XAFPressLogos, XAFExpertQuote
- Data: XAFSpecsTable, XAFComparisonTable, XAFScoreBreakdown,
XAFDecisionMatrix, XAFCalloutBox, XAFQuote, XAFKeyTakeaways,
XAFTableOfContents, XAFMethodology, XAFSurveyResults,
XAFCustomerReviews
- Commerce: XAFHero, XAFProductCard, XAFReviewCard, XAFStickyCTA,
XAFStarRating, XAFBuyButton, XAFAffiliateLink, XAFProsCons,
XAFBestFor, XAFDealAlert, XAFWaitlist
- Legal: XAFDisclosure, XAFArticleDisclosure, XAFAIContentDisclosure,
XAFSponsoredContentDisclosure, XAFHealthDisclaimer, XAFCookieConsent
- Social / growth: XAFNewsletter, XAFExitIntent, XAFSocialProof,
XAFTestimonials, XAFShareReview, XAFPrintButton, XAFReactions,
XAFSearchBar
- Engagement / chrome: XAFReadingProgress, XAFBackToTop,
XAFQuickActions, XAFTagChips
- Schema-specific: XAFHowTo, XAFRecipe
- Media: XAFVideoEmbed, XAFGallery, XAFRelatedProducts,
XAFCompareSlider
Schema composables (in useSchema) emit JSON-LD for Organization, Person,
Product + Review + AggregateRating, FAQPage, BreadcrumbList, WebSite
(with optional SearchAction), Article, HowTo, Recipe, and full meta
tags (title/description/OG/Twitter/canonical/robots) via useSiteMeta.
useAffiliateImpression fires affiliate_impression to window.dataLayer
when a buy button enters the viewport (IntersectionObserver).
XAFHowTo and XAFRecipe emit their own HowTo/Recipe schema internally.
Configure site-wide brand + author + legal + tracking under xAffiliate;
merchant tagging + currency under xAffiliateContent. All 99 components
are auto-imported — no per-file imports.
