Real-World Context & Developer Perspective

Last spring I pushed a product landing page straight from CI. The UI looked sharp, but traffic flat-lined. Google Search Console said the page was indexed; it never showed up for any query. Why? The <title> and <meta name="description"> tags were empty because our CMS template stripped them for drafts. Bots crawled the HTML, saw no signal, and treated the page as low-value fluff.
That flop taught me a hard lesson: on-page SEO isn't optional after the UI is done. It's part of the delivery contract. As developers we own the markup, the server headers, the CI step that validates the page before it hits production. Content writers craft the copy; we wrap it in the right tags, enforce a sane URL scheme, and make sure the page works without a JS bundle.
So, when you spin up a new page, treat the SEO checklist like a lint rule. Run it locally; fail the build if a required tag is missing. You'll avoid the embarrassment of a silent launch. The rest of this guide is the pragmatic, hands-on list that fits into a typical Git-flow: edit, test, merge, deploy.
Architecture & Technical Prerequisites

Before you write a single line of copy, get the page's skeleton right.
URL structure matters more than you think. Keep it short, descriptive, hyphen-separated. For a blog post about "SEO checklist for new pages", a good slug is /blog/seo-checklist-new-pages. Avoid query strings for primary content; they confuse crawlers and dilute link equity.
Every page should declare a <link rel="canonical"> pointing to its own URL. This prevents duplicate-content penalties if the same content is reachable via www and non-www or via HTTP vs. HTTPS. In Apache you can force a single domain with:
#.htaccess
RewriteCond %{HTTP_HOST}!^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
Include the page in your XML sitemap. Most static site generators emit one automatically, but if you're on a headless CMS, add a small script that pings /sitemap.xml after each deployment.
Server headers: the X-Robots-Tag header is a safety net. For public pages you want:
Header set X-Robots-Tag "index, follow"
If you ever need to block a section, switch to noindex, nofollow on that path instead of sprinkling robots.txt rules.
Make sure the HTML starts with a proper HTML5 doctype:
<!DOCTYPE html>
<html lang="en">
…
</html>
And finally, verify the page loads without JavaScript. Run a curl request and check the response body for the <title> and primary H1. If those are generated client-side only, Google will see a blank page and rank you poorly.
Step-by-Step Implementation: Core Setup
Now the meat. Open the template file for the new page and add the following blocks.
Title tag
<title>Simple On-Page SEO Checklist for New Pages | MySite</title>
Keep it under 60 characters. I put the primary keyword first, then the brand.
Meta description
<meta name="description" c>
Google may truncate at 155 characters, so make the first sentence compelling.
H1
<h1>A Simple On-Page SEO Checklist for Every New Website Page</h1>
The H1 should mirror the title closely but can be a bit longer. Don't use multiple H1s; let the hierarchy flow H2 → H3.
Image alt attributes
Every <img> needs an alt. If the image is decorative, use an empty string.
<img src="/assets/checklist.png" alt="On-page SEO checklist screenshot">
Robots.txt sanity check
From the terminal run:
curl -I https://www.example.com/robots.txt | grep -i "User-agent"
If you see Disallow: / for *, you've blocked everything. Fix it in the repo and redeploy.
Trailing-slash consistency
Google treats /page and /page/ as separate URLs. Enforce one style with a tiny.htaccess rule:
# Force trailing slash
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_URI}!\.[a-zA-Z0-9]{1,5}$
RewriteRule ^(.*[^/])$ $1/ [L,R=301]
Pick the style you prefer; just be consistent across the site.
Advanced Configuration & Performance Tuning
With the basics locked down, it's time to squeeze extra value out of the page.
Schema markup (JSON-LD)
Search engines love structured data. For a how-to article, use the HowTo schema:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "Simple On-Page SEO Checklist",
"step": [
{
"@type": "HowToStep",
"url": "https://www.example.com/blog/seo-checklist-new-pages#step1",
"name": "Add title tag",
"text": "Insert a concise title with the primary keyword."
},
{
"@type": "HowToStep",
"url": "https://www.example.com/blog/seo-checklist-new-pages#step2",
"name": "Write meta description",
"text": "Craft a compelling description under 155 characters."
}
]
}
</script>
Paste it right before the closing </head>. I skip inline microdata because JSON-LD is cleaner and easier to test with Google's Rich Results tool.
Open Graph & Twitter Cards
Social previews boost click-through rates. Add these tags:
<meta property="og:title" c>
<meta property="og:description" c>
<meta property="og:image" c>
<meta name="twitter:card" c>
Lazy-loading images
If the page contains several screenshots, add loading="lazy" to each <img>. This reduces initial payload and improves Largest Contentful Paint.
<img src="/assets/checklist.png" alt="Checklist screenshot" loading="lazy">
Core Web Vitals audit
Run Lighthouse locally:
npx lighthouse https://www.example.com/blog/seo-checklist-new-pages --only-categories=performance --view
If LCP exceeds 2.5 s, look at image sizes and server response time. Preload critical resources:
<link rel="preload" href="/css/main.css" as="style">
<link rel="preload" href="/js/main.js" as="script">
And add DNS prefetch for third-party domains (fonts, analytics):
<link rel="dns-prefetch" href="//fonts.gstatic.com">
Automating image compression
I keep an npm script that runs imagemin on the assets/ folder before each build:
"scripts": {
"compress:imgs": "imagemin src/assets/* --out-dir=dist/assets --plugin=pngquant --plugin=mozjpeg"
}
Hook it into your CI:
#.github/workflows/ci.yml
- name: Optimize images
run: npm run compress:imgs
This tiny step shaves off kilobytes, speeds up LCP, and indirectly boosts rankings.
That's the core of a simple on-page SEO checklist for new pages. Follow the steps, automate the repeatable parts, and you'll see crawlers treat your fresh content like a first-class citizen.
Critical Production Pitfalls & Diagnostic Gotchas
Even with a perfect checklist, things still slip when code ships. Here are the gremlins we keep hitting and how to surface them fast.
- Duplicate meta tags – Two
<title>ormeta name="description"tags confuse crawlers. Runcurl -s https://example.com/page.html | grep -iE "title|description"and watch for more than one match. Fix: Keep the first, delete the rest. - Missing or wrong hreflang – International sites often forget to tell Google which language version belongs where. Fire up Lighthouse, open the "Internationalization" panel, and you'll see a warning if
link[rel="alternate"][hreflang]is missing or duplicated. Fix: Add a single<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/page">per language. - Blocked resources in robots.txt – A stray
Disallow: /assets/can hide CSS or JS that Google needs to render the page. Usecurl -I https://example.com/robots.txtand scan forDisallowlines that intersect your/assets/folder. Fix: Remove or whitelist the path. - Accidental
noindex– Onemeta name="robots" con a production page kills visibility. The URL Inspection tool in Search Console instantly flags "Indexed – no". Fix: Delete the tag or change toc.
Quick diagnostic combo:
# 1. Grab raw HTML
curl -s https://example.com/new-page.html > page.html
# 2. Spot duplicate meta
grep -iE "title|description" page.html | sort | uniq -c
# 3. Validate hreflang with Lighthouse (CLI)
lighthouse https://example.com/new-page.html --only-categories=seo --output=json
# 4. Check robots.txt for blocked assets
curl -s https://example.com/robots.txt | grep "Disallow"
Each red flag has a one-liner fix: edit the template, redeploy, re-run the check. That's it.
Comparison & Decision Matrix
Not every project needs the full suite of SEO niceties. Pick a tier that matches your timeline and resources.
| Tier | Time to implement | Impact on rankings | Maintenance overhead | Typical use-case |
|---|---|---|---|---|
| Basic | ≈ 30 min per page | Low – fixes glaring issues only | Minimal – static tags | Landing pages, low-traffic blogs |
| Standard | ≈ 2 hrs per page | Medium – adds structured data and proper canonicals | Low-medium – occasional schema updates | E-commerce product pages, service pages |
| Full-Featured | ≈ 4–6 hrs per page | High – comprehensive signals (FAQ schema, hreflang, lazy-load audit) | High – needs CI step or CMS plugin to stay fresh | Enterprise sites, multilingual portfolios, high-value funnels |
Choose Basic for quick promo pages – a solid title, description, and H1 are enough. Move to Standard once you start scaling product listings; the extra schema pays off in rich snippets. Go Full-Featured only if you have bandwidth to keep markup current, otherwise you'll chase diminishing returns.
Comprehensive FAQ
Do I need a separate meta description for each page?
Yes. Google treats the description as a summary of that exact content. Duplicate descriptions trigger the "duplicate meta description" warning in Search Console and can dilute click-through rates. If you're using a templating engine, inject a page-specific variable, e.g.:
<meta name="description" cDefault fallback') }}">
Even a 150-character tweak that mentions the primary keyword helps.
How often should I audit schema markup?
At least twice a year, or whenever you add a new content type. Use the Rich Results Test or Structured Data Testing Tool. A quick cron job can pull all application/ld+json blocks and compare them against a JSON schema stored in your repo; on failure, raise a ticket.
Can I rely on a CMS plugin for canonical tags?
Plugins are handy, but they can fall out of sync when you change URL structures. I'd skip blind trust in the plugin and add a sanity check in your build pipeline:
# Example Node script
const cheerio = require('cheerio');
const html = fs.readFileSync('dist/page.html');
const $ = cheerio.load(html);
if (!$('link[rel="canonical"]').attr('href')) {
console.error('Missing canonical!');
process.exit(1);
}
If the script fails, you know the plugin missed something.
What's the safest way to test robots directives in staging?
Never point Google at a staging domain. Spin up a local robots.txt that blocks everything, then use the URL Inspection tool's "Test live URL" with the site:staging.example.com prefix. Or run a curl request with a Googlebot header:
curl -A "Googlebot" -I https://staging.example.com/page.html
Look for a 200 status and verify the X-Robots-Tag header if you set one.
Does page speed affect keyword rankings directly?
Google says speed is a ranking factor, but the impact is subtle. Core Web Vitals (LCP, FID, CLS) feed into the algorithm, so a page that consistently scores 90+ will have a slight edge over a sluggish sibling. Use PageSpeed Insights or Lighthouse; aim for LCP < 2.5 s and CLS < 0.1. The real win is lower bounce rates, which indirectly boosts rankings.
Operational Verification Checklist & Next Steps
Before you push to production, run this quick tick-box list:
- ✅ Unique
<title>(≤ 60 chars) - ✅ Meta description present, < 160 chars
- ✅ Single
<h1>containing the target keyword - ✅ All images have descriptive
altattributes - ✅ Structured data block valid (Rich Results Test passes)
- ✅ Canonical tag points to the preferred URL
- ✅ No
noindexunless intentional - ✅ Robots.txt does not block essential assets
- ✅ Lighthouse performance score ≥ 90
Drop the page into your monitoring dashboard (SEO monitoring service) and set a quarterly reminder to run the full audit again. Need help tightening the pipeline? Give us a shout.