Skip to content

In short: a CTA (call to action) is one of the most important elements of a website: it’s the point where a visitor decides whether to become a contact, a customer, a loyal reader. That’s why at PaperPlane we design CTAs case by case: copy, placement, visual hierarchy and timing change for every project. Beneath the design layer, though, there’s a single infrastructure. Flying, our WordPress theme, uses one component to handle all six behaviours a CTA can have, solving accessibility, security and tracking upstream:

  • internal and external links;
  • downloads;
  • mailto;
  • copy-to-clipboard;
  • opening a modal.

A call to action is the most delicate moment on a page. Everything that comes before it (the copy, the images, the content structure, the design) exists to carry the visitor all the way to that button. That’s where it’s decided whether the page worked. And yet, on many WordPress sites, CTAs are treated as a technical detail: a button dropped in quickly, in the theme colour and with little thought around it.

For us it’s exactly the opposite. Designing CTAs is a central part of our web design work, and every project tackles it from scratch.
For a social enterprise, a “Become a volunteer” CTA carries an emotional weight and a placement very different from an “Add to cart” on an e-commerce site or a “Book a call” on a services landing page. The copy changes, the visual hierarchy changes, the number of CTAs on the page changes, the moment they appear changes. These are decisions we make with the client, not with the theme.
But once they’re made, there’s a technical part that does not make sense to reinvent every time: how that button actually works. That’s where Flying comes in.

What a CTA really needs to work well

Think of a typical page on a website. There’s a “Discover the service” button that leads to another page. Further down, “Download the PDF” opens a document. In the sidebar, “Subscribe to the newsletter” brings up a form in a modal window. At the bottom, “Write to us” launches the email client.
Four buttons, four different behaviours. On many WordPress sites these four buttons are added in four different ways: a plugin for the modals, a shortcode for the downloads, a Gutenberg block for the standard buttons, maybe a widget for the mailto.
Four authoring interfaces to learn, four sources of possible errors, four things to update separately. And each one handles accessibility its own way, when it handles it at all.
The result is an inconsistent site: the “Subscribe” button is yellow on the homepage and orange in the sidebar because it comes from a different plugin, “Download” gives no precise information to assistive technologies, the external link doesn’t open the way it should.
Small inconsistencies that, added up, tell the story of a site that wasn’t looked after. And a site that wasn’t looked after converts less.

Six types of CTA, a single interface for whoever publishes

On Flying all these situations go through the same component. Whoever edits a page always sees the same fields: what the button should say (and, if needed, with dedicated text for screen readers), where it should lead, how it should open, what it should look like among the options the project design allows. The rest is automatic.

The six behaviours the component handles cover what we’ve learned over the years building WordPress sites for our clients:

  • Internal link: leads to another page, article or piece of content on the site. Whoever publishes selects the content from a dropdown list, they don’t type URLs;
  • External link: leads to another site. You paste the URL and choose whether to open it in the same window or a new one;
  • Download: downloads a file uploaded to the WordPress library. Typically PDFs, but also images, documents, archives;
  • Mailto and copy-to-clipboard: the first opens the user’s email client with the address pre-filled; the second copies any string to the clipboard: IBANs, discount codes, tax references, technical commands on documentation pages. Decidedly unglamorous use cases, but surprisingly frequent;
  • Modal: opens a dialog window over the page. Typically it contains a form, a video, a notice, or pop-up content that doesn’t warrant a whole page.

Whoever publishes chooses one of these six destinations from a menu, fills in the two or three fields that destination specifically needs, and they’re done. The button is live and works the way it should, with the design conceived for that specific project and with the same technical solidity.

The technical decisions whoever publishes shouldn’t have to make

Here’s the point. Behind the apparently simple choice of “where does this button lead” there are at least four technical decisions that, on a poorly built site, get left to whoever publishes, or worse, get skipped entirely.

Is it a link or an action? A button that leads to another page is semantically a link and should be an <a> tag. A button that opens a modal or copies text is an action and should be a <button>. It sounds like a subtlety, but for anyone navigating with a keyboard or assistive technologies it makes an enormous difference: links and buttons behave differently, and using the wrong one confuses the screen reader and breaks keyboard navigation.

On the Flying component, this decision is made by the code based on the destination chosen. An internal or external link is an <a>; opening a modal or a copy-to-clipboard is a <button>. Whoever publishes isn’t forced to make technical choices.

Does it open in the same window or a new one? For internal links the answer is almost always “same window”: a site that opens new tabs on every click interrupts navigation and lowers conversions. The component handles this automatically: if you’ve chosen an internal link, target="_blank" doesn’t even appear as an option.

Are security attributes needed? Links to external domains that open in a new window must have rel="noopener noreferrer", otherwise the destination site can, in certain scenarios, manipulate the originating page. It’s a good practice documented for years, but on a great many WordPress sites it’s missing because it has to be added by hand and people forget. The component adds it automatically when it detects a domain different from the site’s own.

How is it tracked? CTAs are one of the most important measurement points on a site. Knowing which buttons get clicked, how much and from where, is the basis for understanding whether the page is working and where to step in. Agencies often add Google Analytics event tracking with JavaScript inserted by hand in GTM, one CTA at a time. Our component includes a dedicated field for the tracking class, which whoever manages the site can populate for each individual CTA without touching GTM. Every button, if needed, becomes measurable by default.

On accessibility (the fourth big technical decision whoever publishes shouldn’t have to make) it’s worth spending a whole section.

The accessibility that happens on its own

Imagine publishing a link to a PDF document on an external institutional site, to open in a new window. A very common situation. On a government agency’s site it might be “Download the application form”.

Someone using a screen reader, when they reach that button, should hear something more than “Download the application form, link”. They should also hear that the link will open a new window, and that it leads to a site different from the one they’re on. Without that information, the button is a small trap: you click it and suddenly you’re in a different context, with the page you started from gone or hidden in another tab you don’t know how to manage.

The Flying component composes this message automatically. It generates a span that’s visually hidden but read by screen readers:

<span class="screen-reader-text"> Opens in a new window on an external site</span>

The text changes based on the actual context: “Opens in a new window” if it’s a new window on the same domain, “Opens on an external site” if it’s a different domain but in the same window, “Opens in a new window on an external site” if both. Whoever publishes writes none of this. They choose the destination domain and the window behaviour, the component builds the right message.

The same goes for modals: when the component renders a button that opens a dialog window, it automatically adds the attribute aria-haspopup="dialog", which warns assistive technologies that the button doesn’t lead to another page but opens an overlaid dialog.

They’re details. But they’re the details that separate an accessible site from one that claims to be accessible, and that, conversion-wise, separate a CTA that works for everyone from one that silently excludes a slice of your visitors.

Why the modals are native HTML5

Modal windows have historically been the trickiest case. For years they were handled with dedicated WordPress plugins or JavaScript libraries like Magnific Popup or Fancybox: extra code to load, JavaScript that runs even on pages without modals, accessibility handling that varies from plugin to plugin.

Since 2022 modern browsers natively support the <dialog> element, and our component’s modals are just <dialog>, opened with a single line: showModal(). No libraries to load, no third-party CSS to override. Focus management, closing with the Esc key, the overlay that dims the page behind: all handled by the browser.

The result is less JavaScript sent on every visit, lighter pages and a lower environmental footprint. The conversation about Core Web Vitals isn’t only about optimising images: it’s also about choosing tools that don’t add useless weight.

CTA design: a design decision, not a theme choice

It’s worth clarifying one point, because it might seem that with a single component the CTAs all end up looking the same.
That’s not the case. What Flying standardises is the invisible part: the HTML markup, the accessibility attributes, the security, the tracking.
What it does not standardise is the look, the copy, the position on the page, the number of CTAs, the moment they appear, the hierarchy between primary and secondary.
All of this we design from scratch for every project.

For an institutional site, it can mean a single very prominent CTA per page, with copy that invites a conversation.
For an e-commerce site, a more layered structure with primary (buy), secondary (add to wishlist) and tertiary (share).
For a services landing page, a fixed CTA that follows the scroll.
For a third-sector site, two balanced CTAs (donation and participation) that coexist without a real hierarchy because both matter.

These too are decisions that come out of our design work and out of co-design with the client: we validate them in the design phase, and then implement them in the project’s custom theme.
Flying gives us a solid component that handles every possible behaviour, but we draw the house from scratch every time.

A real limit: the first setup requires a developer

Being honest is part of how we work, so we’ll say it: this approach is extremely simple to use, but the first setup requires a developer.

The fields whoever publishes sees in the WordPress editor (destination, URL, target, tracking class, visual appearance) we modelled ourselves using Advanced Custom Fields. To add a seventh CTA behaviour (let’s imagine: “open WhatsApp with a pre-filled message”) you can’t just tick a box in an admin panel: it means touching the theme’s code. In the same way, to change the visual look of the buttons or add a new style class, you have to go through the theme’s CSS.

For whoever manages content independently, it’s the simplest thing in the world. For whoever wants to build a brand-new behaviour or an unprecedented style from scratch, that’s where we step in. It’s a trade-off consistent with our model: the clients who work with us over the long term aren’t locked into our theme, they’re comfortable in our theme. That’s an important difference.

Simplicity for whoever publishes, maintainability for whoever maintains

A single component for all the CTAs on a site means something very concrete from the standpoint of maintenance over time: there’s only one place to update.

When the WCAG guidelines change and introduce a new best practice, which has already happened several times in recent years, we just need to act on one function.
When a browser introduces a new accessibility attribute, we add it in one place and all the CTAs benefit.
When we want to add a new visual look called for by a project’s design, we add it to a single list of CSS classes.

For our clients this translates into something barely visible but very concrete: no surprises. The CTAs don’t break when we update the site, because there’s a single flow to test. There isn’t one page with the “old” modals and another with the “new” ones, because there aren’t two implementations: there’s only one, and it behaves the same way everywhere. A consistent site is a site that ages better, and a CTA that works today keeps working three years from now.

Where to start if you have a WordPress site

Four concrete questions to judge whether your site’s CTAs are doing their job well.

First: are your CTAs designed, or are they “the theme’s default button”? Do the CTAs have a visual weight consistent with their importance? Is there a clear hierarchy between primary and secondary? Does the copy speak to whoever’s reading or is it generic (“Submit”, “Click here”)? If the answer is “they’re the same everywhere”, there’s probably a conversion margin being left on the table.

Second: are the buttons that open something <button> or <a>? Right-click a CTA that opens a modal or copies text, and look at the HTML. If it’s an <a href="#"> with JavaScript stuck on top, the site is treating actions as navigation: that’s a real accessibility problem.

Third: does someone using a screen reader know a link will open in a new window? Look for a span with a screen-reader-text class or equivalent next to the link text. If it’s not there and the link opens _blank, the screen reader will only read the visible text, and the user will be caught off guard by the unexpected opening.

Fourth: do you have a different plugin for each type of CTA? Open the list of active plugins. How many concern buttons, modals, popups, forms, download managers? If there are more than two, there’s probably room to consolidate.

CTAs are designed, the infrastructure is built once

Call to actions are one of the most important elements for a website’s success. They’re the point where a visitor decides whether to take the step the site is proposing.
That’s why we treat them with the same care we give the homepage copy or the photography on the about page: every project is its own project, every CTA is conceived for that client and its users.
What changes, with us, is what happens underneath. The technical part of CTAs (accessibility, security, tracking, modal window management, HTML semantics) we don’t reinvent every time. Flying solves it, and it only shows in the fact that it works.

If you want to understand how your current site’s CTAs are performing, and where there’s room for improvement (both in the design and in the technical part), write to us. Half an hour of conversation can clarify more than you’d think.