Skip to content

Track inline links to CTA destinations - #5860

Open
Yndira-E wants to merge 11 commits into
mainfrom
feat/track-inline-cta-links
Open

Yndira-E wants to merge 11 commits into
mainfrom
feat/track-inline-cta-links

Conversation

@Yndira-E

@Yndira-E Yndira-E commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Description

Follow-up to #5857: inline links to one of the five CTA destinations now fire that destination's PostHog event (cta-sign-up, cta-book-demo, etc.), while the link text stays free to fit the sentence.

  • CtaLink is the one component for inline CTA links. The href and event come from CTA_DESTINATIONS, the text goes in the slot, and it sends { position, variant: 'text' }.
  • Markdown needs no changes: ProseA renders CtaLink whenever a link points at a destination, however it was written (cta:signUp, site:appURL or a typed URL). That covers around 280 existing links in posts, changelog entries and webinars. Links to site:appURL ("FlowFuse Cloud is already running 0.6") count as cta-sign-in.
  • The inline CTA links on the homepage, OPC UA page and ROI calculator now use CtaLink. The homepage one had a hand-written capture().
  • CtaImage renders through CtaLink, so its href comes from CTA_DESTINATIONS and it fires the destination event (variant: 'image') alongside blog-cta.
  • The five CTA buttons and CtaLink take a query prop (e.g. { subject: 'Certified Nodes' } or utm parameters) appended to the fixed URL, so a link that needs one no longer has to be hand-written. cta:contactUs?subject=... works in markdown too.
  • A link matches a destination by its path: the trailing slash, the query string and the absolute flowfuse.com form don't matter, while a hash (/pricing/#comparison) counts as its own destination. The CtaCustom guards now use the same rule. A new test fails npm test when a custom destination duplicates another or points at a reserved one, or when a .vue file hard-codes a link to a reserved one. Until now these checks only threw at render time, which doesn't fail the build.

Follow-up:

Related Issue(s)

Checklist

  • I have read the contribution guidelines
  • I have considered the performance impact of these changes
  • Suitable unit/system level tests have been added and they pass
  • Documentation has been updated
  • For blog PRs, an Art Request has been created (instructions)

Note

Add CtaLink and markdown cta: tracking for CTA destinations

  • Introduces CtaLink component and markdown cta: syntax to render and track inline links to registered CTA destinations.
  • Adds ctaDestinationKey, withCtaQuery, and ctaQuery helpers in cta-destinations.ts to resolve URLs and manage query parameters.
  • Updates ProseA and CtaImage to render matching links via CtaLink, and adds a query prop to fixed CTA components.
  • Replaces manual link tracking in index.vue, opcua.vue, and roi-calculator.vue with CtaLink.
  • Risk: ctaDestinationKey treats URLs with hashes as separate links and ignores query strings for destination matching. Custom CTA registry validation now uses this resolver, which may reject absolute URLs or query strings that collide with reserved destinations. npm test now fails on hard-coded reserved CTA links.
📊 Macroscope summarized 4cf4d89. 18 files reviewed, 3 issues evaluated, 0 issues filtered, 3 comments posted

🗂️ Filtered Issues

Every markdown link renders through a ProseA wrapper that fires the
destination's cta-* event with position inline-link when its href is one
of the five CTA destinations. Link text stays free-form.
ProseA renders CtaLink for markdown links to a CTA destination, so both
share one component. Migrates the inline links on the homepage, OPC UA
and ROI calculator pages.
Image CTAs now take their href from CTA_DESTINATIONS and fire the
destination's cta-* event (variant image) alongside blog-cta.
CtaCustom and the custom destination registry now match reserved
destinations with ctaDestinationKey, so a query string, hash or absolute
URL no longer slips past. A new test loads the registry and fails npm test
when a .vue file hard-codes a link to one of the five destinations, since a
render-time throw doesn't fail the build.
A hash points at a section of the page, so /pricing/#comparison is no
longer treated as the reserved pricing destination. Query strings still
are.
The five buttons and CtaLink take a query prop (e.g. subject or utm
parameters) appended to the fixed href, so a link that needs one no
longer has to be hand-written. The path, label and event stay fixed.
cta:<key> in markdown accepts a query string too.
@netlify

netlify Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for flowfuse-website ready!

Name Link
🔨 Latest commit 512d1df
🔍 Latest deploy log https://app.netlify.com/projects/flowfuse-website/deploys/6ab655157f84ff0008ae27da
😎 Deploy Preview https://deploy-preview-5860--flowfuse-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 43 (🟢 up 8 from production)
Accessibility: 95 (no change from production)
Best Practices: 92 (no change from production)
SEO: 92 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread nuxt/components/CtaLink.vue
Comment thread nuxt/lib/cta-destinations.ts Outdated
Comment thread nuxt/utils/remark-site-links.ts
ctaQuery collapsed a repeated parameter (?tag=one&tag=two) to its last
value. A query value can now be an array, which withCtaQuery writes back
as the repeated parameter.
Comment thread nuxt/lib/cta-destinations.ts
A destination link written with http:// was treated as an ordinary link.
The comparison now upgrades the protocol but keeps the host, so another
site's /pricing/ still doesn't match.
Comment thread nuxt/lib/cta-destinations.ts Outdated
HTTPS://... links now match their destination, and a query parameter named
toString, constructor or __proto__ no longer picks up an inherited value.
@Yndira-E
Yndira-E requested a review from ZJvandeWeg September 25, 2026 11:12
@Yndira-E
Yndira-E marked this pull request as ready for review September 25, 2026 11:22

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant