agentspeed.
← all fixes
Issue remediation

Unclear primary call-to-action

Agents can't tell what action your page wants users to take, so they don't recommend it for buying or signup queries.

failed checkmarkup.title
What this means

The primary call-to-action (CTA) is the single highest-intent thing a visitor can do on a page: buy this product, start a free trial, book a demo, sign up, download the app. "Unclear primary CTA" means the page either has no obvious CTA, has many competing CTAs of equal weight, or buries the CTA inside ambiguous copy. From an agent's perspective, this looks like a page with no purpose, and agents prefer pages with crisp purposes when answering action-oriented queries.

Why it matters for AI agents

AI shopping agents and task agents are increasingly the funnel: a user asks Claude or ChatGPT 'help me find a CRM and start a trial' and the agent picks one. To pick yours, the agent needs to extract the next action ("start a free trial," "book a demo," "buy now") from your page in plain text. Pages with one prominent CTA in semantic HTML (a real <a> or <button> with descriptive text) win. Pages where the CTA is a styled <div> with onClick handlers, or where every section has its own competing button, lose.

Business impact

For commerce: agents that can identify your "Add to cart" or "Buy now" button in the rendered HTML are eligible for Agentic Commerce flows (Stripe Agent Pay, OpenAI shopping). Pages that hide the action behind a JavaScript-rendered modal are not. For SaaS: agents recommending tools embed the CTA URL directly in the answer; if the agent cannot identify the trial-start URL, your competitor's answer wins. The fix is mostly a copy-and-markup audit, not infrastructure.

How to check manually

Open your most-trafficked landing page. Read the first viewport (no scrolling) and ask: what is the one thing this page wants me to do? If you can't answer in five words, the CTA is unclear. Then view-source and confirm the CTA is a real <a href="…"> or <button> with descriptive text ("Start free trial," "Add to cart," "Book a demo"). If the action label is generic ("Click here," "Learn more"), agents can't map it to a user intent.

The exact fix

Pick one primary CTA per page. Make it a real anchor or button with text that names the action explicitly. Place it above the fold, repeat it after the value proposition, and avoid putting four equally-styled secondary CTAs (Twitter, GitHub, Docs, Pricing) at the same visual weight. If the page has multiple legitimate paths (sign up vs. learn more), use visual hierarchy: one dominant button, one ghost-style secondary.

Copy-paste snippet
Reference snippethtmllanding-page.html
<header>
  <h1>Stop manually copying expense receipts.</h1>
  <p class="lede">Acme reads your inbox, categorises expenses, and hands them
     to your accountant. Free for the first 30 days.</p>

  <!-- Primary CTA: descriptive label, real <a> with destination URL,
       visually dominant. -->
  <a href="/signup" class="btn btn-primary">Start your free trial</a>

  <!-- Secondary CTA: lower visual weight, no competition with primary. -->
  <a href="/demo" class="btn btn-ghost">Book a 15-minute demo</a>
</header>
Platform-specific implementations

The reference snippet above is platform-agnostic. Below are the concrete steps for the four most common stacks plus a generic fallback for any other host.

Next.js

Replace any styled-div onClick patterns with real <Link> or <button> elements. <Link href> is the canonical above-the-fold CTA; it ships in initial HTML, agents can extract it, and it works without JS. Reserve <button> for actions that are not navigation (e.g. "Add to cart" that triggers a server action). Don't lazy-load the CTA from a client component; primary CTAs belong in server components so they're in the agent-readable HTML.

Next.jstsxapp/page.tsx
import Link from 'next/link';

export default function Home() {
  return (
    <header>
      <h1>Stop manually copying expense receipts.</h1>
      <p>Acme reads your inbox and hands expenses to your accountant.</p>

      {/* Server-rendered, in initial HTML, agent-extractable. */}
      <Link href="/signup" className="btn btn-primary">
        Start your free trial
      </Link>
      <Link href="/demo" className="btn btn-ghost">
        Book a demo
      </Link>
    </header>
  );
}

WordPress

Most CTA breakage on WordPress comes from page builders (Elementor, Divi, Beaver Builder) generating <div onclick=…> instead of real anchors. Audit your CTA blocks and use the page builder's "Button" widget set to anchor mode rather than a custom HTML block. Confirm the rendered output by view-source; every CTA should be <a href="…"> with semantic text, not a styled div.

WordPresshtmlElementor button block (Advanced → HTML Tag)
<!-- Wrong: opens via JS, agents can't extract destination. -->
<div class="btn-primary" onclick="window.location='/signup'">Start trial</div>

<!-- Right: real anchor, agent-readable, works without JS. -->
<a class="btn-primary" href="/signup">Start your free trial</a>

Shopify

Shopify's product page comes with an "Add to cart" form by default, and that is the primary CTA. The breakage usually comes from custom themes that replace the <button type="submit"> with a JS-driven UI, or homepages that pile on six equal-weight buttons ("Shop Mens," "Shop Womens," "Read Blog," "Newsletter," …). On product pages, keep the native form. On the homepage, pick one path: usually "Shop the catalogue" or a single bestselling collection.

Shopifyliquidsections/main-product.liquid
<form method="post" action="/cart/add">
  <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">

  <!-- Real <button type="submit"> — agents can identify it as the
       primary action and AI shopping agents can fill it. -->
  <button type="submit" class="btn-primary">
    Add to cart — {{ product.price | money }}
  </button>
</form>

Webflow

Use the Button element (which renders as <a> by default) for navigation CTAs and the Form Submit button for in-page actions. Don't style <div>s as buttons. Webflow makes the right element easy to use, but custom Embed blocks tempt people into <div onclick=…> patterns. Open the page in Designer and confirm every CTA is a Button or Link Block element (not a Div Block).

WebflowtxtWebflow Designer → Element settings
Hero CTA → Link Block element with "btn-primary" class
Secondary CTA → Link Block, "btn-ghost" class, lower visual weight
Footer CTAs → Link Block, smallest visual weight

Avoid: Div Block with click interaction. The interaction works in
the browser but gives agents no destination URL.

Static HTML / any stack

Hand-author <a> and <button> elements with descriptive text. The static-site advantage: there is no framework getting in the way. Pick one CTA per page, mark it up semantically, give it a class for styling, and keep the secondary CTAs visually subordinate. If you're using Tailwind / utility CSS, keep the dominant button's classes obviously distinct from the secondary's.

Static HTML / any stackhtmlindex.html
<section class="hero">
  <h1>Stop copying receipts.</h1>
  <p>Acme reads your inbox and categorises expenses automatically.</p>

  <a href="/signup" class="btn-primary">Start your free trial</a>
  <a href="/demo" class="btn-ghost">Book a 15-minute demo</a>
</section>
Common mistakes
How to re-test

View source on your top three pages and confirm exactly one prominent <a> or <button> with descriptive label appears in the first viewport. Run a fresh AgentSpeed scan, and the actionability category score will tick up. Test the page through an AI shopping agent or by asking ChatGPT/Claude "what action should I take on this page?"; the answer should match your intended primary CTA.

FAQ
Can I have more than one CTA?

Yes. Most pages have a primary and a secondary. The rule is visual hierarchy: the primary should be unambiguously dominant. Two CTAs of equal weight create choice paralysis for humans and ambiguity for agents.

Does the CTA copy affect agent behaviour?

Yes. Agents read the button text verbatim and use it as the action label in their answers. "Start free trial" maps cleanly to a trial-start intent; "Get started" is ambiguous (start what?). Specific, action-verb-led copy wins.

What about cookie banners that block the CTA?

Cookie banners that overlay the entire page until dismissed are agent-blocking and human-frustrating. Use a non-modal banner (bottom strip, dismissable corner card) or a delayed fold-down so the primary CTA is visible on first paint.

Verify on your site
Run a scan

Free scan, no signup. The score page is permanent and citable, so you can link it from your team's remediation ticket alongside this guide for “Unclear primary call-to-action”.

Run a free scan →See all fixes →