Skip to content

CtaImage: support custom destinations - #5901

Merged
Yndira-E merged 5 commits into
mainfrom
cta-image-custom-destination
Oct 1, 2026
Merged

Yndira-E merged 5 commits into
mainfrom
cta-image-custom-destination

Conversation

@sumitshinde-84

@sumitshinde-84 sumitshinde-84 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Description

::cta-image could only link to the four fixed destinations (sign-up, demo, contact, pricing). This adds cta="custom", which links to an entry in CUSTOM_CTA_DESTINATIONS, so an inline image CTA can point at a blueprint, another blog post, a docs page, or a product page.

::cta-image{src="/blog/2025/12/images/my-image.png" alt="Read the OPC UA node docs" cta="custom" destination-key="opcuaCertifiedNodeDocs"}
::
  • cta="custom" requires a destination-key from nuxt/lib/custom-cta-destinations.ts, the same registry CtaCustom uses. A destination-key on any other cta value is an error.
  • The registry supplies the URL and the event, so there's no free-form href, and the registry's own self-check already rejects reserved destinations and duplicate URLs.
  • Only entries with a fixed href are accepted. Dynamic-URL entries (e.g. latestWebinar) are rejected for now and can be handled separately.
  • On click, a custom image fires the registered destination event with { position: 'inline-image', variant: 'image' }, plus blog-cta with the article reference, cta_type: custom and destination_key. No URL is sent to PostHog.
  • The four fixed values still render through CtaLink, unchanged.
  • The rules live in nuxt/lib/cta-image.ts. nuxt/lib/cta-image.test.mjs checks every ::cta-image in the content tree against them, so a bad one fails npm test, not just the page render.
  • Handbook (marketing/content-strategy/blog) and .claude/CLAUDE.md document the new option.

@sumitshinde-84
sumitshinde-84 requested a review from a team as a code owner October 1, 2026 09:24
@sumitshinde-84
sumitshinde-84 requested review from Yndira-E and removed request for a team October 1, 2026 09:27
@netlify

netlify Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for flowfuse-website ready!

Name Link
🔨 Latest commit 5c719e4
🔍 Latest deploy log https://app.netlify.com/projects/flowfuse-website/deploys/6abe85174c7e610008d0ebaf
😎 Deploy Preview https://deploy-preview-5901--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: 44 (🟢 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.

@Yndira-E

Yndira-E commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

@sumitshinde-84 this overlaps with #5860, opened in response to what ZJ was asking in #5857 (comment).

Would you mind reviewing that one first? It already has a more robust reserved-destination check (ctaDestinationKey, hash/query-aware, with build-time test coverage via npm test) than this PR's render-time-only sameSite check.

Once #5860 lands, please rework this one on top of that.

Reworked on top of #5860: reserved destinations are matched with
ctaDestinationKey, and every ::cta-image in the content tree is checked
in npm test instead of only at render time.
@sumitshinde-84
sumitshinde-84 force-pushed the cta-image-custom-destination branch from 2445b92 to 6612551 Compare October 1, 2026 11:05
Comment thread nuxt/content/handbook/marketing/content-strategy/blog.md
Co-authored-by: Yndira Escobar <129537638+Yndira-E@users.noreply.github.com>
@Yndira-E

Yndira-E commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Would it make sense for custom image CTAs to reference an entry in CUSTOM_CTA_DESTINATIONS instead of accepting a free-form href?

For example:

::cta-image{src="/images/cta/5-whys.png" alt="Read the 5 Whys article" cta="custom" destination-key="blog5Whys"}
::

The registry could provide the destination URL and its event. On click, CtaImage could emit that destination event with position: 'inline-image' and variant: 'image', as well as the shared blog-cta event with the article reference and destination_key. That would let us compare all inline image CTAs through one consistent event while still tracking each destination through its registered event. It would also avoid passing a free-form URL to PostHog or maintaining a separate destination map. For registered fixed destinations, the URL should come from the registry; dynamic URLs could be handled separately.

WDYT?

cta="custom" now takes a destination-key into the shared registry instead
of a free-form href. The registry supplies the URL and the destination
event, fired with position inline-image and variant image, alongside
blog-cta with destination_key. Only entries with a fixed href are accepted.
@sumitshinde-84

Copy link
Copy Markdown
Contributor Author

Would it make sense for custom image CTAs to reference an entry in CUSTOM_CTA_DESTINATIONS instead of accepting a free-form href?

For example:

::cta-image{src="/images/cta/5-whys.png" alt="Read the 5 Whys article" cta="custom" destination-key="blog5Whys"}
::

The registry could provide the destination URL and its event. On click, CtaImage could emit that destination event with position: 'inline-image' and variant: 'image', as well as the shared blog-cta event with the article reference and destination_key. That would let us compare all inline image CTAs through one consistent event while still tracking each destination through its registered event. It would also avoid passing a free-form URL to PostHog or maintaining a separate destination map. For registered fixed destinations, the URL should come from the registry; dynamic URLs could be handled separately.

WDYT?

Thanks @Yndira-E, applied! cta="custom" now takes a destination-key into CUSTOM_CTA_DESTINATIONS instead of a free-form href. The registry supplies the URL and event; on click it fires the destination's event (position: 'inline-image', variant: 'image') plus blog-cta with the article reference and destination_key. Dynamic-URL entries are rejected for now, and npm test checks every ::cta-image in content. Ready for another look.

@Yndira-E

Yndira-E commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Thanks @sumitshinde-84

Nice work. Putting the rules in lib/cta-image.ts and checking every ::cta-image in npm test is the right call. Tests pass on this branch. A few small things:

  1. Handbook (blog.md): "There is no default…" is still indented under the sign-up bullet, so it reads as part of it. Can you move it above the custom bullet or de-indent it?
  2. Examples: blog5Whys (PR description) and blueprintLibrary (handbook) aren't in CUSTOM_CTA_DESTINATIONS, so copying them fails the test. Use an existing key or note that the entry must be added first.
  3. CLAUDE.md: the new bullet says custom images render a plain link, not CtaLink, but the later bullet still says "Renders through CtaLink". Can you scope that one to the four fixed values?
  4. Question: ULink here has no external/target, unlike CtaCustom (external: true). That's fine today, but the first external registry entry would go through Vue Router. Handle now or document?

Link custom images with external, fix the handbook example and indent,
scope the CtaLink note in CLAUDE.md, and resolve custom images in the RSS feed.
@sumitshinde-84

Copy link
Copy Markdown
Contributor Author

Thanks for the review, all your points are addressed ! On the external link question, I handled it now: the custom ULink gets external, the same default as CtaCustom, so it always does a full page load. I also found that the RSS feed has its own copy of the image destinations, so a custom image would have appeared there without a link. It now gets its link from the registry too.

Comment thread nuxt/content/handbook/marketing/content-strategy/blog.md Outdated
@Yndira-E
Yndira-E enabled auto-merge October 1, 2026 16:08
@Yndira-E
Yndira-E merged commit b281edb into main Oct 1, 2026
7 checks passed
@Yndira-E
Yndira-E deleted the cta-image-custom-destination branch October 1, 2026 16:13
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.

2 participants