---
title: "Write SEO user stories that engineering accepts and ships"
description: "Turn SEO requests into user stories with testable acceptance criteria and a business case, so engineering can estimate, accept, and ship them."
canonical: "https://scalewithsearch.com/articles/seo-user-stories-engineering"
date: "2026-03-20"
modified: "2026-09-25"
---
## Site navigation

- [Scale With Search](https://scalewithsearch.com/)
- Real estate
  - Real estate
    - [Real estate](https://scalewithsearch.com/for/real-estate)
- Work
  - Start here
    - [Send your brief](https://scalewithsearch.com/work#send-your-brief)
    - [Prepare your six-question brief](https://scalewithsearch.com/work#prepare-your-six-question-brief)
  - Build
    - [Site build, content library with SEO, signal desk](https://scalewithsearch.com/work)
- For your business
  - Trades and home services
    - [Auto body and collision shops](https://scalewithsearch.com/for/auto-body-and-collision-shops)
    - [Foundation and home repair contractors](https://scalewithsearch.com/for/foundation-and-home-repair)
    - [Garage door and fencing contractors](https://scalewithsearch.com/for/garage-door-and-fencing-contractors)
    - [HVAC contractors](https://scalewithsearch.com/for/hvac-contractors)
    - [Janitorial and commercial cleaning companies](https://scalewithsearch.com/for/janitorial-and-commercial-cleaning)
    - [Locksmiths](https://scalewithsearch.com/for/locksmiths)
    - [Moving companies](https://scalewithsearch.com/for/moving-companies)
    - [Pest control companies](https://scalewithsearch.com/for/pest-control-companies)
    - [Plumbing and electrical contractors](https://scalewithsearch.com/for/plumbing-and-electrical-contractors)
    - [Restoration and water or fire damage companies](https://scalewithsearch.com/for/restoration-and-water-fire-damage)
    - [Roofing companies](https://scalewithsearch.com/for/roofing-companies)
    - [Towing companies](https://scalewithsearch.com/for/towing-companies)
    - [Tree services and landscaping companies](https://scalewithsearch.com/for/tree-services-and-landscaping)
    - [Solar installers](https://scalewithsearch.com/for/solar-installation)
    - [General contractors](https://scalewithsearch.com/for/general-contractors-and-construction)
    - [Paving, concrete, and flooring contractors](https://scalewithsearch.com/for/paving)
  - Practices and professional services
    - [Bookkeeping and tax practices](https://scalewithsearch.com/for/bookkeeping-and-tax-practices)
    - [Dental practices](https://scalewithsearch.com/for/dental-practices)
    - [Family and criminal defense law firms](https://scalewithsearch.com/for/family-and-criminal-defense-law-firms)
    - [Med spas and aesthetics practices](https://scalewithsearch.com/for/med-spas-and-aesthetics)
    - [Personal injury law firms](https://scalewithsearch.com/for/personal-injury-law-firms)
    - [Veterinary clinics](https://scalewithsearch.com/for/veterinary-clinics)
    - [Gyms and fitness studios](https://scalewithsearch.com/for/fitness)
    - [Therapy and outpatient health practices](https://scalewithsearch.com/for/therapy-and-outpatient-health)
    - [Medical billing companies](https://scalewithsearch.com/for/medical-billing)
    - [Insurance agencies](https://scalewithsearch.com/for/insurance-agencies)
    - [Financial advisors](https://scalewithsearch.com/for/financial-advisors)
    - [Property management companies](https://scalewithsearch.com/for/property-management)
    - [Recruiting and staffing agencies](https://scalewithsearch.com/for/recruiting-and-staffing)
    - [Architects and interior designers](https://scalewithsearch.com/for/architects-and-interior-designers)
    - [Logistics and supply chain companies](https://scalewithsearch.com/for/logistics-and-supply-chain)
  - Agencies, MSPs, and manufacturing
    - [IT and managed service providers](https://scalewithsearch.com/for/it-and-managed-service-providers)
    - [Machine shops and precision manufacturers](https://scalewithsearch.com/for/machine-shops-and-precision-manufacturing)
    - [Marketing agencies and freelancers](https://scalewithsearch.com/for/marketing-agencies-and-freelancers)
    - [SEO agencies and consultants](https://scalewithsearch.com/for/seo-agencies-and-consultants)
    - [Small manufacturers and fabricators](https://scalewithsearch.com/for/small-manufacturers-and-fabricators)
  - Restaurants, shops, studios, and nonprofits
    - [Restaurants and hospitality businesses](https://scalewithsearch.com/for/restaurants-and-hospitality)
    - [Retail stores and ecommerce sellers](https://scalewithsearch.com/for/retail-and-ecommerce)
    - [Photographers, event planners, and travel agents](https://scalewithsearch.com/for/photographers)
    - [Churches and nonprofits](https://scalewithsearch.com/for/churches-and-nonprofits)
  - [All industries](https://scalewithsearch.com/for/)
- Learn
  - For your office
    - [Office job guides](https://scalewithsearch.com/guides/)
    - [Browser calculators](https://scalewithsearch.com/tools/)
  - Start here
    - [How it works](https://scalewithsearch.com/how-it-works)
    - [Free Starter Kit](https://scalewithsearch.com/kit/business-memory-starter-kit.zip)
    - [Synthetic specimen](https://scalewithsearch.com/specimen/working-session-specimen.zip)
  - Guides
    - [The Complete Guide to Business Memory for AI Agents](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [The Complete Small-Business Guide to AI Agent Governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [The Complete Guide to Leaving Vendor AI Memory](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - Articles by cluster
    - [Business memory](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [Agent governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [Migration and ownership](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - For machines
    - [llms.txt](https://scalewithsearch.com/llms.txt)
    - [llms-full.txt](https://scalewithsearch.com/llms-full.txt)
    - [Machine view](https://scalewithsearch.com/?view=machine)
- Company
  - Evidence
    - [Proof](https://scalewithsearch.com/proof)
  - Company
    - [About](https://scalewithsearch.com/about)

# Write SEO user stories that engineering accepts and ships.

An SEO ticket arrives in the engineering backlog: "Improve page speed." Nobody knows which pages, which metric, or what counts as done. The ticket sits for three sprints. Then someone closes it.

Engineering teams reject SEO work for four predictable reasons. The requirement is vague. The ticket has no business case. The acceptance criteria cannot be tested. The ticket reads like a marketing wish list, not an engineering specification.

Persuasion does not fix this. Write SEO work in the format engineering already uses. That format is a user story with a clear requirement, testable acceptance criteria, and a measured business effect.

This translation is the product manager's job. The SEO practitioner knows what must change. The developer knows how to build it. You write the story that both sides can work from. You do not need deep technical SEO knowledge for this. Get the requirement and the check from the SEO practitioner, then add the business case and the story format.

## Find the defects in a rejected ticket

### Vague requirements

"Improve page speed" gives a direction but no target. It does not name the pages, the metric, the threshold, or the measurement method.

Compare this version:

"As a mobile user, I expect the product listing page to load its largest visible element within 2.5 seconds, so that I can browse without delay."

The second version names the page, the metric (Largest Contentful Paint, or LCP), the threshold, and the device. It also names the user benefit. An engineer can estimate it, build it, and test it.

### Acceptance criteria that nobody can test

Many SEO tickets describe a result but not a way to verify it. "Implement structured data on product pages" gives the developer no definition of correct.

Write each criterion so that a developer can check it without SEO knowledge:

- The page source contains a JSON-LD block.
- The page passes the Google Rich Results Test with zero errors.
- The product name, price, availability, and rating fields come from CMS data.
- The server-rendered page and the client-rendered page output the same schema.
- A test in the CI pipeline validates the schema on each deployment.

Each criterion is binary. It passes or it fails. Nobody has to interpret it.

### No business case

An engineering backlog holds more requests than the team can ship. Each ticket competes for sprint capacity. An SEO ticket without a business case loses to a feature request that has a revenue projection.

Attach numbers to each SEO story. This example uses sample figures:

"This page receives 15,000 organic impressions each month. It ranks in position 8 with a 1.2% click-through rate (CTR). Technical fixes can support a move to positions 3 to 5, where we estimate a CTR of 5 to 8%. That move adds about 570 to 1,020 clicks each month. At our organic conversion rate of 3.2%, that is 18 to 33 more conversions each month."

Take the CTR estimate for each position from your own Search Console data, not from an industry average. With the numbers attached, the stakes are visible to the engineer.

Put SEO stories through the same prioritization as feature stories. A quantified SEO story can compete on equal terms with a quantified feature story. [RICE scoring for SEO](/articles/rice-scoring-seo-prioritization) gives one method for that comparison.

## Use one template for each SEO story

```text
As a [user, crawler, or system],
I need [specific technical requirement],
so that [measurable business outcome].

Acceptance criteria:
- [ ] Criterion 1 (pass or fail)
- [ ] Criterion 2 (pass or fail)
- [ ] Criterion 3 (pass or fail)

Business context:
[Data that supports the priority: traffic, revenue, competitive effect]

Technical notes:
[Implementation hints that do not prescribe the architecture]
```

The three examples below use this template. Their figures are sample data. Replace them with numbers from your own Search Console and analytics accounts.

### Example: fix LCP on product pages

```text
As a mobile user on product pages,
I need the largest contentful paint to render within 2.5 seconds,
so that our pages pass Core Web Vitals and fewer visitors leave
before the page loads.

Acceptance criteria:
- [ ] LCP < 2.5s on mobile (Lighthouse CI, simulated 4G)
- [ ] Hero image uses WebP or AVIF, with width and height attributes
- [ ] Third-party scripts load after the LCP element renders
- [ ] Hero image causes no layout shift (CLS contribution = 0)
- [ ] Lighthouse CI check in the PR pipeline fails builds over 2.5s LCP

Business context:
Product pages bring 62% of organic traffic. Google Search Console
reports that 43% of product page URLs fail the LCP threshold.
These URLs receive about 8,400 organic sessions each month.

Technical notes:
The current LCP bottleneck is the hero image (a 2.1 MB PNG) and a
render-blocking chat widget. The image CDN already converts images
to WebP through a URL parameter.
```

This story gives the developer the metric, the threshold, the pages, the check, the business stakes, and hints that shorten the work.

### Example: add Product structured data

```text
As a search engine crawler on our product pages,
I need valid JSON-LD Product schema on each product detail page,
so that Google can show rich results (price, availability, reviews)
and more searchers click through.

Acceptance criteria:
- [ ] JSON-LD block in the head of each product detail page
- [ ] Type Product with the required fields (name, description, image,
      offers.price, offers.priceCurrency, offers.availability)
- [ ] Review and AggregateRating fields present when the product has 1+ reviews
- [ ] Zero errors in the Google Rich Results Test for any product URL
- [ ] Schema values match the visible page content
- [ ] Unit test validates the schema output against schema.org
- [ ] Schema is in the server-rendered output, not injected on the client only

Business context:
2,400 product pages have no structured data. Team estimate: rich
results lift CTR on product queries by 20 to 30%. At current
impressions, that is about 1,200 more clicks each month.
Measure the real lift after release.

Technical notes:
The page component state already holds the product data. Generate the
schema from the same data object that fills the visible product details.
Reference: schema.org/Product
```

The implementation detail for this story is in [JSON-LD structured data for developers](/articles/structured-data-jsonld-developers).

### Example: fix canonical tags on category pages

```text
As a search engine that evaluates our category pages,
I need each category page to declare one canonical URL
that ignores sort and filter parameters,
so that Google consolidates ranking signals on one URL
and does not split them across parameter variations.

Acceptance criteria:
- [ ] Each category page contains <link rel="canonical" href="[URL]">
- [ ] The canonical URL is absolute (https:// and the domain)
- [ ] The canonical URL drops the sort and filter parameters
- [ ] Paginated pages (page 2, 3, and later) canonical to themselves
- [ ] The canonical URL matches the URL in the XML sitemap
- [ ] The canonical tag is in the server-rendered and client-rendered HTML
- [ ] Automated test: the canonical URL returns a 200 status code

Business context:
Google Search Console reports 340 category URLs with the status
"Duplicate without user-selected canonical". These pages receive
12,000 impressions each month, split across parameter variations.

Technical notes:
The CMS appends sort and filter parameters to category URLs. The
canonical tag strips them and points at the base category path.
The existing URL normalization middleware can hold this logic.
```

The pagination criterion corrects an older practice. Google Search Central's guidance on ecommerce pagination says to give each page in a sequence its own canonical URL. Do not point page 2 at page 1. [Canonical tags for developers](/articles/canonical-tags-developers) covers the other canonical edge cases.

## Write acceptance criteria that pass engineering review

### Make each criterion testable without SEO knowledge

A developer verifies each criterion with developer tools, an automated test, or a standard validation service. "Improves SEO" is not testable. "JSON-LD validates with zero errors in the Google Rich Results Test" is testable by anyone with a browser.

### Name the measurement tool

Do not assume that the developer knows how to verify an SEO requirement. Put the tool in the criterion:

- "LCP < 2.5s, measured by Lighthouse CI with the mobile preset"
- "Schema validates at search.google.com/test/rich-results"
- "Canonical tag visible in `curl -s [URL] | grep canonical`"
- "Page appears in the XML sitemap at /sitemap.xml"

### Separate required criteria from optional ones

Put a MoSCoW label, or a similar priority label, on each acceptance criterion:

- **Must:** the story is not accepted until this criterion passes. It blocks the release.
- **Should:** expected for quality, but not a blocker. A follow-up story can cover it.
- **Could:** an improvement to consider later.

The labels stop scope creep inside one story. They also tell the engineer what "done" means.

### Pair each criterion with a regression test

Where possible, map each acceptance criterion to an automated test. The test stops the defect from coming back. If LCP must stay under 2.5 seconds, a Lighthouse CI check in the deployment pipeline enforces it on each release. If canonical tags must be absolute, a crawl-time check validates each URL. [SEO testing in a CI/CD pipeline](/articles/seo-testing-ci-cd-pipeline) shows how each story becomes a permanent quality gate.

## Size SEO stories for sprint planning

| Task | Typical size | Sprint effect |
|---|---|---|
| Add canonical tags to a page template | Small (1 to 2 story points) | Fits in any sprint |
| Add JSON-LD schema for one page type | Medium (3 to 5 story points) | Half a sprint for one developer |
| Improve LCP for a page template | Medium to large (5 to 8 story points) | Needs a performance profile first |
| Fix JavaScript rendering for SEO | Large (8 to 13 story points) | Can need architecture changes |
| Move a URL structure with redirects | Extra large (13+ story points) | An epic across several sprints |

These estimates help you put SEO work into sprints at a realistic rate. An SEO initiative of 40 story points does not fit in a two-week sprint beside feature work. Break it into smaller stories and spread them across several sprints.

One or two SEO stories in each sprint is a sustainable rate for most teams. That is about 10 to 20% of sprint capacity. A team that depends more on organic traffic can give more capacity while it builds the foundation.

### Attach SEO stories to related feature work

SEO stories ship most reliably when they travel with a related feature. Suppose engineering builds a new product page template. Put the structured data story and the canonical story in the same sprint. The SEO work adds scope, often 15 to 20%. It ships with the feature and does not compete against it. The [SEO sprint planning guide](/articles/seo-sprint-planning-guide) shows how to fit organic work into your current sprint cadence.

### Split work that crosses teams

When one requirement needs several teams, write one story for each team. Link the stories as dependencies in your project management tool. A structured data rollout can need three stories, in this order:

1. A backend story that generates JSON-LD from the data layer.
2. A frontend story that puts the JSON-LD block in the page template.
3. A QA story that validates the output across page types.

Each team gets a story sized for its capacity. The dependency chain stays visible to all three teams.

## Treat a high estimate as information

Sometimes engineering estimates your SEO story much higher than you expected. The estimate shows complexity that you did not see. Before you push back, ask why the number is high.

If an architectural constraint drives the estimate, break the story into smaller parts. Or schedule the prerequisite work first. If the developer does not know the SEO requirement well, a 30-minute walkthrough often brings the estimate down.

----

```text
                  .|########||.                                       .|########||.                                       .|########||.
               |##||.      .||##|.                                 |##||.      .||##|.                                 |##||.      .||##|.
             |#|.              .|#|.                             |#|.              .|#|.                             |#|.              .|#|.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
        .#.                          .#|                    .#.                          .#|                    .#.                          .#|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
      |#             ......             #|                |#             ......             #|                |#             ......             #|
     .#           ||#########|           #|              .#           ||#########|           #|              .#           ||#########|           #|
    .#.         |######||######|.        .#.            .#.         |######||######|.        .#.            .#.         |######||######|.        .#.
    #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#
   ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||
   #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #
 ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||
 #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#
 #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.
.|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||
||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||
#.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#
#    .||####|###########################|.     #    #    .||####|###########################|.     #    #    .||####|###########################|.     #
#      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #
#      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #
#      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #
#      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #
#   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #
#. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#
|| |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||
|| ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||
.# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.
 #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#
 ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||
  #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.
   ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||
    #.        .######|#|#########|        .#            #.        .######|#|#########|        .#            #.        .######|#|#########|        .#
    .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.
     |#           ||########||           #.              |#           ||########||           #.              |#           ||########||           #.
      |#             ......             #|                |#             ......             #|                |#             ......             #|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
        |#.                          .#.                    |#.                          .#.                    |#.                          .#.
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
            .|#|.              .|#|.                            .|#|.              .|#|.                            .|#|.              .|#|.
               |##||.      .||##|                                  |##||.      .||##|                                  |##||.      .||##|
                 .||########||.                                      .||########||.                                      .||########||.

Scale With Search  2026  [scalewithsearch.com](https://scalewithsearch.com)
```
