Generate complete SEO meta tags for every page. Covers title patterns, meta descriptions, Open Graph, Twitter Cards, and JSON-LD structured data (LocalBusiness, Service, FAQ, BreadcrumbList). Use when: building pages, adding social sharing, implementing structured data, optimizing for search engines.
89
Does it follow best practices?
If you maintain this skill, you can automatically optimize it using the tessl CLI to improve its score:
npx tessl skill review --optimize ./path/to/skillValidation for skill structure
Status: Production Ready ✅ Last Updated: 2026-01-14 Source: Schema.org, Open Graph Protocol, Twitter Developer Docs
Every page needs:
<head>
{/* Basic SEO */}
<title>Service in Location | Brand Name</title>
<meta name="description" content="Value prop. Differentiator. Call to action." />
<link rel="canonical" href="https://example.com/page" />
{/* Open Graph */}
<meta property="og:title" content="Service in Location" />
<meta property="og:description" content="Value prop. Differentiator. CTA." />
<meta property="og:image" content="https://example.com/og-image.jpg" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="website" />
{/* Twitter Card */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Service in Location" />
<meta name="twitter:description" content="Value prop. Differentiator. CTA." />
<meta name="twitter:image" content="https://example.com/og-image.jpg" />
{/* JSON-LD Structured Data */}
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Business Name",
"description": "What we do",
"@id": "https://example.com",
"url": "https://example.com",
"telephone": "+61-XXX-XXX-XXX",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main St",
"addressLocality": "Sydney",
"addressRegion": "NSW",
"postalCode": "2000",
"addressCountry": "AU"
}
})}
</script>
</head>Character Limits:
Page Type Formulas:
| Page Type | Pattern | Example |
|---|---|---|
| Home | [Brand] - [Primary Service] in [Location] | Acme Plumbing - 24/7 Emergency Plumber Sydney |
| Service | [Service] in [Location] | [Brand] | Hot Water Repairs Sydney | Acme Plumbing |
| Location | [Service] [Suburb] | [Brand] | Plumber Bondi | Acme Plumbing |
| About | About [Brand] - [Tagline/USP] | About Acme - Licensed Plumbers Since 1995 |
| Contact | Contact [Brand] - [Location] | [Phone] | Contact Acme Plumbing - Sydney | 1300 XXX XXX |
Title Modifiers (add credibility):
Anti-Patterns (avoid):
Character Limits:
Formula:
[Value prop] [Service] in [Location]. [Differentiator]. [CTA].Examples by Page Type:
Home Page:
Fast, reliable plumbing services in Sydney. 24/7 emergency response, licensed plumbers, upfront pricing. Call 1300 XXX XXX for same-day service.Service Page:
Expert hot water repairs in Sydney. Fix or replace electric, gas & solar systems. Licensed technicians, 1-year warranty. Book online or call 1300 XXX XXX.Location Page:
Trusted plumber in Bondi. Blocked drains, leaks, hot water, gas fitting. Same-day service, upfront quotes. Call your local plumber on 1300 XXX XXX.Power Words (use sparingly):
Required Tags:
<meta property="og:title" content="Service in Location" />
<meta property="og:description" content="Value prop. Differentiator. CTA." />
<meta property="og:image" content="https://example.com/og-image.jpg" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="website" />Image Requirements:
og:type Values by Page Type:
| Page Type | og:type |
|---|---|
| Home, Service, Location | website |
| Blog Post | article |
| Business Profile | business.business |
Optional but Recommended:
<meta property="og:site_name" content="Brand Name" />
<meta property="og:locale" content="en_AU" />Card Types:
| Type | Use Case |
|---|---|
| summary | Small square image (1:1), basic info |
| summary_large_image | Large image (1.91:1), most common |
Required Tags:
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Service in Location" />
<meta name="twitter:description" content="Value prop. Differentiator. CTA." />
<meta name="twitter:image" content="https://example.com/og-image.jpg" />Optional:
<meta name="twitter:site" content="@yourbrand" />
<meta name="twitter:creator" content="@authorhandle" />Fallback Behavior:
Best Practice: Define og:* tags first, only add twitter:* if values differ.
Use for homepage and contact page:
{
"@context": "https://schema.org",
"@type": "Plumber",
"name": "Acme Plumbing",
"description": "Licensed plumbing services in Sydney",
"@id": "https://acmeplumbing.com.au",
"url": "https://acmeplumbing.com.au",
"logo": "https://acmeplumbing.com.au/logo.png",
"image": "https://acmeplumbing.com.au/og-image.jpg",
"telephone": "+61-XXX-XXX-XXX",
"email": "info@acmeplumbing.com.au",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main Street",
"addressLocality": "Sydney",
"addressRegion": "NSW",
"postalCode": "2000",
"addressCountry": "AU"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": -33.8688,
"longitude": 151.2093
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "07:00",
"closes": "17:00"
}
],
"sameAs": [
"https://facebook.com/acmeplumbing",
"https://instagram.com/acmeplumbing"
]
}Specific Business Types (instead of generic LocalBusiness):
Use for service pages:
{
"@context": "https://schema.org",
"@type": "Service",
"name": "Hot Water Repairs",
"description": "Fast hot water system repairs in Sydney",
"provider": {
"@type": "Plumber",
"name": "Acme Plumbing",
"url": "https://acmeplumbing.com.au"
},
"areaServed": {
"@type": "City",
"name": "Sydney"
},
"availableChannel": {
"@type": "ServiceChannel",
"serviceUrl": "https://acmeplumbing.com.au/hot-water-repairs",
"servicePhone": "+61-XXX-XXX-XXX"
}
}Use for FAQ sections:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How much does a plumber cost in Sydney?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Plumbing rates in Sydney typically range from $100-$150 per hour for standard work. Emergency callouts may incur higher rates. We provide upfront quotes before starting work."
}
},
{
"@type": "Question",
"name": "Do you offer same-day service?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, we offer same-day plumbing service across Sydney for urgent repairs. Call us before 2pm for same-day availability."
}
}
]
}Use on all pages except homepage:
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://acmeplumbing.com.au"
},
{
"@type": "ListItem",
"position": 2,
"name": "Services",
"item": "https://acmeplumbing.com.au/services"
},
{
"@type": "ListItem",
"position": 3,
"name": "Hot Water Repairs",
"item": "https://acmeplumbing.com.au/hot-water-repairs"
}
]
}When to Use:
Self-Referencing Canonical:
<!-- Always include, even if no duplicates -->
<link rel="canonical" href="https://example.com/page" />Pagination:
<!-- On page 2+ -->
<link rel="canonical" href="https://example.com/services" />
<!-- Not https://example.com/services?page=2 -->Common Mistakes:
Check Your Implementation:
| Tool | Purpose | URL |
|---|---|---|
| Google Rich Results Test | Test structured data | search.google.com/test/rich-results |
| Schema Markup Validator | Validate JSON-LD | validator.schema.org |
| Facebook Debugger | Test Open Graph tags | developers.facebook.com/tools/debug |
| Twitter Card Validator | Test Twitter Cards | cards-dev.twitter.com/validator |
| Screaming Frog | Audit all pages | screamingfrog.co.uk/seo-spider |
Browser Extensions:
For every page, include:
<title> (50-60 chars, unique per page)<meta name="description"> (150-160 chars, unique per page)<link rel="canonical"> (absolute URL)Never:
| Issue | Cause | Fix |
|---|---|---|
| No rich snippets in search | Invalid JSON-LD | Use validator.schema.org, check commas/quotes |
| Social share shows wrong image | og:image missing or wrong size | Use 1200x630px, test with Facebook Debugger |
| Title truncated in search | Too long | Keep under 60 chars |
| Description truncated | Too long | Keep under 160 chars |
| Multiple pages rank for same keyword | Duplicate titles | Make each title unique |
Title Tags:
Meta Descriptions:
Open Graph:
JSON-LD:
Canonical URLs:
Production Notes:
fa91c34
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.