takescake

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:

  1. What type of card is it? (Legendary Creature — Human Wizard)
  2. What does it do? (The oracle text)
  3. 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:

  1. It's how players identify cards
  2. It's searchable (people search "legendary creature wizard")
  3. 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:

  1. Impressions: How often our pages appear in search results
  2. Click-through rate: % of impressions that result in clicks
  3. Average position: Where we rank for card name queries
  4. 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:

  1. Card name
  2. Card type
  3. Card text
  4. Card image
  5. 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.

Related Posts