X Enterprises
Composables

useAffiliateContent

Review-site composable — merchant config lookup, idempotent link tagging, Intl price formatting, and GTM click tracking.

useAffiliateContent

The review-site composable. Resolves merchant config, performs idempotent merchant link tagging, formats prices with Intl.NumberFormat, and pushes affiliate_click events to window.dataLayer. Auto-imported — no per-file imports needed.

Usage

const {
  config,        // Resolved XAffiliateContentConfig
  getMerchant,   // (id: MerchantId) => XAffiliateContentMerchant
  hasTag,        // (id: MerchantId) => boolean
  taggedUrl,     // (merchant, url) => string — idempotent
  taggedLink,    // (link: AffiliateLink) => AffiliateLink
  formatPrice,   // (amount: number) => string
  trackClick,    // (payload) => void — pushes affiliate_click to dataLayer
} = useAffiliateContent()

Returns

KeyTypeDescription
configComputedRef<XAffiliateContentConfig>Reactive app config under the xAffiliateContent namespace.
getMerchant(id)(MerchantId) => XAffiliateContentMerchantResolved merchant config (displayName, ctaLabel, color, tagValue, tagParam). Throws if merchant is not configured.
hasTag(id)(MerchantId) => booleantrue if the merchant has a non-empty tagValue.
taggedUrl(merchant, url)(XAffiliateContentMerchant, string) => stringAppends the merchant's tag param if missing. Idempotent — re-running on an already-tagged URL returns it unchanged.
taggedLink(link)(AffiliateLink) => AffiliateLinkReturns a new AffiliateLink with taggedUrl(merchant, url) applied.
formatPrice(amount)(number) => stringIntl.NumberFormat(locale, { style: 'currency', currency }) — uses xAffiliateContent.locale and xAffiliateContent.currency.
trackClick(payload)({ url, merchant, position?, originalUrl? }) => voidPushes affiliate_click to window.dataLayer if loaded; no-op otherwise.

Idempotent tagging

taggedUrl checks whether the URL already carries the merchant's tagParam (using URLSearchParams) — if so, it returns the URL unchanged. This means you can safely call taggedUrl on URLs from your CMS, user input, or imported data without double-tagging.

const merchant = getMerchant('amazon')

taggedUrl(merchant, 'https://amazon.com/dp/B0CX123')
// → 'https://amazon.com/dp/B0CX123?tag=yourtag-20'

taggedUrl(merchant, 'https://amazon.com/dp/B0CX123?tag=already-tagged')
// → 'https://amazon.com/dp/B0CX123?tag=already-tagged'  (unchanged)

Click tracking payload

trackClick({
  url: 'https://amazon.com/dp/B0CX123?tag=yourtag-20',
  merchant: 'amazon',        // MerchantId
  position: 'hero',          // optional — set by XAFBuyButton's position prop
  originalUrl: 'https://amazon.com/dp/B0CX123',
})
// → pushes to window.dataLayer:
//   { event: 'affiliate_click', merchant: 'amazon', url: '...',
//     originalUrl: '...', position: 'hero' }

If GTM is not loaded, window.dataLayer.push is a no-op — safe to ship without GTM.

Examples

Custom buy button using useAffiliateContent

<script setup>
const { getMerchant, taggedUrl, formatPrice, trackClick } = useAffiliateContent()
const merchant = getMerchant('amazon')

const url = taggedUrl(merchant, 'https://amazon.com/dp/B0CX123')
const priceLabel = formatPrice(29.99)

function onClick() {
  trackClick({
    url,
    merchant: 'amazon',
    position: 'sidebar',
    originalUrl: 'https://amazon.com/dp/B0CX123',
  })
}
</script>

<template>
  <a :href="url" rel="sponsored noopener noreferrer" target="_blank" @click="onClick">
    Check price on {{ merchant.displayName }} — {{ priceLabel }}
  </a>
</template>

Skip a merchant that's not tagged

const { hasTag, taggedUrl } = useAffiliateContent()

function safeTag(merchantId, url) {
  if (!hasTag(merchantId)) return url
  return taggedUrl(getMerchant(merchantId), url)
}

AI Context

composable: useAffiliateContent
package: "@xenterprises/nuxt-x-affiliate"
use-when: >
  Review-site functionality — merchant config lookup, idempotent merchant
  link tagging, Intl price formatting, and GTM/GA4 click tracking.
  taggedUrl() is idempotent — re-running on an already-tagged URL returns
  it unchanged. formatPrice() uses xAffiliateContent.locale and
  xAffiliateContent.currency. trackClick() pushes affiliate_click to
  window.dataLayer when GTM is loaded (no-op otherwise). All XAF
  review-site components use this composable under the hood — use it
  directly when you need a custom-styled CTA.
Copyright © 2026