Rethinking Card Page SEO: From Marketing to User Intent
2025-10-04
Rethinking Card Page SEO: From Marketing to User Intent
When optimizing for search engines, it's tempting to stuff keywords and promote features. But the best SEO comes from giving users exactly what they expect. Today I want to share how we completely rethought our card page metadata - and why simpler ended up being better.
The Old Approach: Feature-First
Our original card page titles looked like this:
<title>Gisa and Geralf | Find Similar Cards with Gemma AI Semantic Search</title>
The description mixed card information with site features:
<meta name="description" content="Gisa and Geralf is a powerful Commander card.
Discover similar cards using Gemma embeddings and semantic similarity.
Find synergies with AI-powered search...">
What We Were Thinking
- ā Mention Gemma embeddings (our unique tech)
- ā Reference semantic search (differentiation)
- ā Include AI keywords (trending topic)
- ā Promote features (value proposition)
This seemed smart. We have cool technology, so let's tell people about it!
What Users Actually Wanted
When someone searches "Gisa and Geralf MTG" on Google, they want to know:
- What type of card is it? (Legendary Creature ā Human Wizard)
- What does it do? (The oracle text)
- Where can I see/buy it? (Images and pricing)
They're not searching for semantic similarity features. They're searching for the card itself.
The New Approach: Card-First
We completely redesigned our metadata to match user intent.
New Title Format
<title>Gisa and Geralf | Legendary Creature ā Human Wizard</title>
Simple. Clean. Shows the card name and full type line (including subtypes).
For non-creatures (like Aura spells):
<title>Rancor | Enchantment ā Aura</title>
The type line immediately tells users what kind of card this is.
New Description: Pure Oracle Text
<meta name="description" content="When Gisa and Geralf enters, mill four cards.
Once during each of your turns, you may cast a Zombie creature spell from your
graveyard. | Takescake.com - Your MTG Card Companion">
Now users see the actual card rules in search results. For cards without oracle text (like basic lands), we fall back to:
<meta name="description" content="Gisa and Geralf - Legendary Creature ā Human Wizard |
Takescake.com - Your MTG Card Companion">
Streamlined Keywords
Old keywords (17 terms):
Gisa and Geralf, MTG, Magic the Gathering, Commander, EDH,
Gemma embeddings, semantic similarity, AI card search,
semantic MTG, find similar cards, card synergies,
deck building AI, ML card discovery, Gemma semantic search,
TCGplayer prices, card oracle text, Commander synergies
New keywords (6 terms):
Gisa and Geralf, MTG, Magic the Gathering, Commander,
TCGplayer price, Legendary Creature ā Human Wizard
We kept only what's essential and directly relevant to the card.
Why This Works Better
1. Matches Search Intent
When users search for a card name, Google now shows:
Search: "gisa and geralf mtg"
Result:
Gisa and Geralf | Legendary Creature ā Human Wizard
When Gisa and Geralf enters, mill four cards. Once during
each of your turns, you may cast a Zombie creature spell...
This immediately answers their question. No marketing fluff. No feature promotion. Just card info.
2. Improves Click-Through Rate
Users are more likely to click results that directly address their query. Before, our listings looked like ads:
"Find Similar Cards with Gemma AI Semantic Search" ā Sounds promotional
After, they look like information:
"Legendary Creature ā Human Wizard" ā This is what I searched for!
3. Better for Long-Tail Search
People search in different ways:
- "gisa and geralf commander" ā Now matches because "Commander" isn't buried in AI keywords
- "gisa and geralf zombie" ā Now matches because oracle text mentions "Zombie"
- "gisa and geralf legendary creature" ā Now matches because type line is in title
The oracle text itself provides natural keyword coverage.
4. Social Sharing Feels Natural
When users share card pages on Discord or Twitter, the preview now shows:
Title: Gisa and Geralf | Legendary Creature ā Human Wizard
Description: When Gisa and Geralf enters, mill four cards...
Image: The card artwork
This looks like a card reference, not a promotional post. Other players immediately recognize it as useful information.
5. Consistent with User Expectations
Every other MTG database (Scryfall, Gatherer, EDHREC) shows:
- Card name
- Type line
- Oracle text
By matching this convention, we feel familiar and trustworthy.
Implementation Details
Dynamic Metadata Generation
Each card page dynamically generates metadata based on the card data:
export async function generateMetadata({
params
}: {
params: { oracle: string }
}): Promise<Metadata> {
const all = await loadCards();
const versions = listVersionsForOracle(all, params.oracle, ...);
const main = versions[0];
// Build clean title
const typeLine = main.type_line || 'Magic Card';
const title = `${main.name} | ${typeLine}`;
// Use oracle text as description
const oracleText = main.oracle_text || '';
const tagline = 'Takescake.com - Your MTG Card Companion';
const description = oracleText
? `${oracleText} | ${tagline}`
: `${main.name} - ${typeLine} | ${tagline}`;
// Minimal, relevant keywords
const keywords = [
main.name,
'MTG',
'Magic the Gathering',
'Commander',
'TCGplayer price',
typeLine
];
return {
title,
description,
keywords: keywords.join(', '),
openGraph: {
title,
description,
type: 'website',
images: [cardImage]
}
};
}
This runs server-side for every card page, ensuring each has unique, optimized metadata.
Type Line Formatting
Type lines can be complex:
- Simple: "Creature ā Dragon"
- Legendary: "Legendary Creature ā Human Wizard"
- Multi-type: "Legendary Enchantment Creature ā God"
- Auras: "Enchantment ā Aura"
- Instants/Sorceries: Just "Instant" or "Sorcery"
We include the full type line because:
- It's how players identify cards
- It's searchable (people search "legendary creature wizard")
- It provides context without needing to read oracle text
Image Priority
We also fixed image resolution to prioritize local images:
// 1. Try local downloaded image (specific print)
const directLocalPath = `/cards/${featuredCard.id}-normal.jpg`;
// 2. Fall back to manifest lookup (oracle-based)
const manifestImg = getCardImagePath(manifest, featuredCard.oracle_id, 'large');
// 3. Last resort: Scryfall remote URL
const scryfallFallback = card.image_uris?.large || card.image_uris?.normal;
const finalImage = directLocalPath || manifestImg || scryfallFallback;
Local images load faster and work better for social media previews (especially with the ?art=
parameter for alternate arts).
Testing and Validation
Google Search Console
After deploying these changes, we'll monitor:
- Impressions: How often our pages appear in search results
- Click-through rate: % of impressions that result in clicks
- Average position: Where we rank for card name queries
- Query analysis: What terms are driving traffic
We expect:
- ā Higher CTR (clearer, more relevant titles)
- ā More long-tail traffic (oracle text provides natural keywords)
- ā Better positions for "{card name} + mtg/commander" queries
Build Verification
All changes compile cleanly:
npm run build
ā Compiled successfully
ā Linting and checking validity of types
ā Collecting page data
ā Generating static pages (33/33)
No errors. No warnings. Just clean metadata.
Manual Testing
Checked several card types:
- Creatures: Show type line with subtypes
- Enchantments: Include "Enchantment ā Aura" when applicable
- Instants/Sorceries: Simple one-word type
- Planeswalkers: Include "ā Chandra" style suffix
- Lands: Often no oracle text, fall back gracefully
All render correctly in:
- Google search results preview
- Twitter card validator
- Facebook Open Graph debugger
- Discord link previews
Comparison: Before and After
Before (Marketing-Heavy)
Title: Find Similar Cards with Gemma AI Semantic Search
Description: Discover card synergies using AI-powered semantic similarity...
Keywords: Gemma embeddings, semantic search, ML card discovery, ...
Feel: Promotional, feature-focused, tech-forward
Google sees: A page promoting AI search technology
User sees: "What is this site trying to sell me?"
After (Information-First)
Title: Legendary Creature ā Human Wizard
Description: When Gisa and Geralf enters, mill four cards...
Keywords: MTG, Magic the Gathering, Commander, TCGplayer price
Feel: Reference material, straightforward, helpful
Google sees: A page about a specific Magic card
User sees: "Perfect! This is the card info I need."
Lessons Learned
1. Trust Your Content
Magic cards are inherently keyword-rich:
- Names are unique and searchable
- Type lines include game terms
- Oracle text contains mechanics and card names
- Set names and symbols provide context
We don't need to add SEO keywords - the cards already have them.
2. Features Belong in Content, Not Metadata
Our semantic search and Gemma embeddings are great features! But they belong:
- In blog posts (like this one)
- On feature pages (/search, /deck)
- In site descriptions (homepage, about)
Not on every card page title.
3. Match User Mental Models
Players think of cards as:
Card Name (Set) - Type Line
Oracle Text
Price
Not as:
AI-Powered Semantic Search Result
Gemma Embedding Vector Match
ML-Suggested Card Synergy
Our metadata should reflect how players actually conceptualize cards.
4. Simplicity Scales Better
With 100,000+ cards in our database:
- Simple metadata is easier to generate
- Less prone to bugs or edge cases
- Faster to render
- Easier to maintain
Complex marketing-heavy titles would require constant tweaking and A/B testing.
What We Kept
Not everything changed! We still:
- Include all printings of each card
- Show TCGplayer prices with affiliate links
- Provide related card suggestions
- Offer semantic search (just not in every title)
- Display detailed card info (legality, rulings, etc.)
The features are still there. We just stopped shouting about them in metadata.
Next Steps
Short-term (Next 2 Weeks)
- Monitor Google Search Console metrics
- Track CTR changes on card pages
- Observe social sharing patterns
Medium-term (Next Month)
- Analyze which type lines drive most traffic
- Identify high-value oracle text keywords
- Optimize image loading for faster social previews
Long-term (Next Quarter)
- Implement FAQ schema for common card questions
- Add structured data for specific card types
- Create landing pages for popular mechanics
Conclusion
Good SEO isn't about cramming keywords or promoting features. It's about understanding what users want and giving them exactly that.
For card pages, users want:
- Card name
- Card type
- Card text
- Card image
- Where to buy it
Everything else is a distraction.
By simplifying our metadata to focus on these core elements, we've created:
- More relevant search results
- Higher click-through rates (projected)
- Better social sharing experience
- Easier maintenance
- Scalable approach for 100K+ cards
Sometimes the best optimization is subtraction.
Technical Note: Changes in app/cards/[oracle]/page.tsx
. Build verified clean. Metadata now dynamically generated per card. Average page load time unchanged.
Try it: Visit any card page and view the page source - you'll see clean, focused metadata that actually describes the card.