Skip to content

Advanced Examples

Rumen Damyanov edited this page Sep 22, 2025 · 1 revision

Advanced Examples

Comprehensive examples demonstrating advanced usage patterns, real-world scenarios, and best practices with the PHP-SEO package.

Complete E-commerce Implementation

Product Page SEO

<?php

use Rumenx\PhpSeo\SeoManager;
use Rumenx\PhpSeo\Config\SeoConfig;

class ProductSeoManager
{
    private SeoManager $seoManager;
    private array $defaultConfig;

    public function __construct()
    {
        $this->defaultConfig = [
            'default_title' => 'E-commerce Store',
            'default_description' => 'Premium products at great prices',
            'meta_tags' => [
                'author' => 'E-commerce Store',
                'robots' => 'index,follow',
                'og:site_name' => 'E-commerce Store',
                'twitter:site' => '@ecommercestore'
            ],
            'structured_data' => [
                'enabled' => true,
                'default_publisher' => [
                    'name' => 'E-commerce Store',
                    'logo' => 'https://store.com/logo.jpg'
                ]
            ]
        ];

        $config = new SeoConfig($this->defaultConfig);
        $this->seoManager = new SeoManager($config);
    }

    public function generateProductSeo(array $product): array
    {
        $content = $this->buildProductHtml($product);
        
        $options = [
            'type' => 'product',
            'title' => $product['name'] . ' - ' . $product['brand'],
            'description' => $this->generateProductDescription($product),
            'keywords' => $this->generateProductKeywords($product),
            'url' => $product['url'],
            'image' => $product['images'][0] ?? null,
            'product_data' => [
                'name' => $product['name'],
                'brand' => $product['brand'],
                'sku' => $product['sku'],
                'price' => $product['price'],
                'currency' => $product['currency'],
                'availability' => $product['in_stock'] ? 'in_stock' : 'out_of_stock',
                'condition' => $product['condition'] ?? 'new',
                'images' => $product['images'],
                'reviews' => $product['reviews'] ?? []
            ]
        ];

        $analysis = $this->seoManager->analyze($content, $options);

        return [
            'meta_tags' => $analysis->getMetaTags(),
            'structured_data' => $analysis->generateStructuredData(),
            'recommendations' => $analysis->getRecommendations(),
            'social_tags' => $this->generateSocialTags($product),
            'breadcrumbs' => $this->generateBreadcrumbs($product)
        ];
    }

    private function buildProductHtml(array $product): string
    {
        return "
            <div class='product' itemscope itemtype='http://schema.org/Product'>
                <h1 itemprop='name'>{$product['name']}</h1>
                <div class='brand' itemprop='brand'>{$product['brand']}</div>
                <div class='description' itemprop='description'>
                    {$product['description']}
                </div>
                <div class='price' itemprop='offers' itemscope itemtype='http://schema.org/Offer'>
                    <span itemprop='price'>{$product['price']}</span>
                    <span itemprop='priceCurrency'>{$product['currency']}</span>
                </div>
                <div class='images'>
                    " . implode('', array_map(function($img) {
                        return "<img src='{$img['url']}' alt='{$img['alt']}' itemprop='image'>";
                    }, $product['images'])) . "
                </div>
                <div class='features'>
                    " . implode('', array_map(function($feature) {
                        return "<div class='feature'>{$feature}</div>";
                    }, $product['features'] ?? [])) . "
                </div>
            </div>
        ";
    }

    private function generateProductDescription(array $product): string
    {
        $description = $product['short_description'] ?? substr(strip_tags($product['description']), 0, 155);
        return $description . ' | Free shipping available.';
    }

    private function generateProductKeywords(array $product): array
    {
        $keywords = [$product['name'], $product['brand']];
        
        if (isset($product['category'])) {
            $keywords[] = $product['category'];
        }
        
        if (isset($product['tags'])) {
            $keywords = array_merge($keywords, $product['tags']);
        }

        return array_unique($keywords);
    }

    private function generateSocialTags(array $product): string
    {
        $tags = [
            '<meta property="product:brand" content="' . htmlspecialchars($product['brand']) . '">',
            '<meta property="product:availability" content="' . ($product['in_stock'] ? 'in stock' : 'out of stock') . '">',
            '<meta property="product:condition" content="' . ($product['condition'] ?? 'new') . '">',
            '<meta property="product:price:amount" content="' . $product['price'] . '">',
            '<meta property="product:price:currency" content="' . $product['currency'] . '">'
        ];

        return implode("\n", $tags);
    }

    private function generateBreadcrumbs(array $product): array
    {
        return [
            ['name' => 'Home', 'url' => '/'],
            ['name' => $product['category'] ?? 'Products', 'url' => '/category/' . ($product['category_slug'] ?? 'products')],
            ['name' => $product['name'], 'url' => $product['url']]
        ];
    }
}

Category Page SEO

class CategorySeoManager
{
    private SeoManager $seoManager;

    public function generateCategorySeo(array $category, array $products): array
    {
        $content = $this->buildCategoryHtml($category, $products);
        
        $options = [
            'type' => 'webpage',
            'title' => $category['name'] . ' - Shop Online',
            'description' => $this->generateCategoryDescription($category, count($products)),
            'url' => $category['url'],
            'image' => $category['image'] ?? null,
            'keywords' => $this->generateCategoryKeywords($category, $products)
        ];

        $analysis = $this->seoManager->analyze($content, $options);

        return [
            'meta_tags' => $analysis->getMetaTags(),
            'structured_data' => $this->generateCategoryStructuredData($category, $products),
            'recommendations' => $analysis->getRecommendations(),
            'pagination_tags' => $this->generatePaginationTags($category)
        ];
    }

    private function generateCategoryStructuredData(array $category, array $products): string
    {
        $itemList = [
            '@context' => 'https://schema.org',
            '@type' => 'ItemList',
            'name' => $category['name'],
            'numberOfItems' => count($products),
            'itemListElement' => []
        ];

        foreach ($products as $index => $product) {
            $itemList['itemListElement'][] = [
                '@type' => 'ListItem',
                'position' => $index + 1,
                'item' => [
                    '@type' => 'Product',
                    'name' => $product['name'],
                    'url' => $product['url'],
                    'image' => $product['image'],
                    'offers' => [
                        '@type' => 'Offer',
                        'price' => $product['price'],
                        'priceCurrency' => $product['currency']
                    ]
                ]
            ];
        }

        return json_encode($itemList, JSON_PRETTY_PRINT);
    }
}

Blog and Content Management

Article SEO System

class ArticleSeoManager
{
    private SeoManager $seoManager;

    public function generateArticleSeo(array $article): array
    {
        $content = $this->prepareArticleContent($article);
        
        $options = [
            'type' => 'article',
            'title' => $article['title'],
            'description' => $article['excerpt'] ?? $this->generateExcerpt($article['content']),
            'url' => $article['url'],
            'image' => $article['featured_image'],
            'author' => $article['author']['name'],
            'published_at' => $article['published_at'],
            'modified_at' => $article['updated_at'] ?? $article['published_at'],
            'keywords' => $this->extractKeywords($article),
            'reading_time' => $this->calculateReadingTime($article['content'])
        ];

        $analysis = $this->seoManager->analyze($content, $options);

        return [
            'meta_tags' => $analysis->getMetaTags(),
            'structured_data' => $this->generateArticleStructuredData($article),
            'social_tags' => $this->generateSocialMediaTags($article),
            'recommendations' => $analysis->getRecommendations(),
            'related_articles' => $this->findRelatedArticles($article)
        ];
    }

    private function generateArticleStructuredData(array $article): string
    {
        $schema = [
            '@context' => 'https://schema.org',
            '@type' => 'Article',
            'headline' => $article['title'],
            'description' => $article['excerpt'] ?? $this->generateExcerpt($article['content']),
            'image' => $this->processImageForSchema($article['featured_image']),
            'author' => [
                '@type' => 'Person',
                'name' => $article['author']['name'],
                'url' => $article['author']['url'] ?? null,
                'image' => $article['author']['avatar'] ?? null
            ],
            'publisher' => [
                '@type' => 'Organization',
                'name' => 'Blog Name',
                'logo' => [
                    '@type' => 'ImageObject',
                    'url' => 'https://blog.com/logo.jpg'
                ]
            ],
            'datePublished' => $article['published_at'],
            'dateModified' => $article['updated_at'] ?? $article['published_at'],
            'mainEntityOfPage' => [
                '@type' => 'WebPage',
                '@id' => $article['url']
            ]
        ];

        // Add article sections if available
        if (!empty($article['sections'])) {
            $schema['articleSection'] = $article['sections'];
        }

        // Add word count
        $schema['wordCount'] = str_word_count(strip_tags($article['content']));

        return json_encode($schema, JSON_PRETTY_PRINT);
    }

    private function calculateReadingTime(string $content): int
    {
        $wordCount = str_word_count(strip_tags($content));
        return max(1, round($wordCount / 200)); // 200 words per minute
    }

    private function extractKeywords(array $article): array
    {
        $keywords = [];
        
        // From tags
        if (!empty($article['tags'])) {
            $keywords = array_merge($keywords, $article['tags']);
        }
        
        // From categories
        if (!empty($article['categories'])) {
            $keywords = array_merge($keywords, $article['categories']);
        }
        
        // From content analysis
        $contentKeywords = $this->analyzeContentKeywords($article['content']);
        $keywords = array_merge($keywords, $contentKeywords);
        
        return array_unique(array_slice($keywords, 0, 10));
    }

    private function analyzeContentKeywords(string $content): array
    {
        // Simple keyword extraction (in real implementation, use more sophisticated NLP)
        $text = strtolower(strip_tags($content));
        $words = preg_split('/\W+/', $text);
        $words = array_filter($words, function($word) {
            return strlen($word) > 3 && !in_array($word, $this->getStopWords());
        });
        
        $frequency = array_count_values($words);
        arsort($frequency);
        
        return array_slice(array_keys($frequency), 0, 5);
    }

    private function getStopWords(): array
    {
        return ['this', 'that', 'with', 'have', 'will', 'from', 'they', 'know', 'want', 'been', 'good', 'much', 'some', 'time', 'very', 'when', 'come', 'here', 'just', 'like', 'long', 'make', 'many', 'over', 'such', 'take', 'than', 'them', 'well', 'were'];
    }
}

Multi-language SEO

International SEO Manager

class InternationalSeoManager
{
    private SeoManager $seoManager;
    private array $languages;
    private string $defaultLanguage;

    public function __construct(array $languages = ['en', 'es', 'fr', 'de'], string $defaultLanguage = 'en')
    {
        $this->languages = $languages;
        $this->defaultLanguage = $defaultLanguage;
        $this->seoManager = new SeoManager();
    }

    public function generateMultiLanguageSeo(array $page, string $currentLanguage): array
    {
        $content = $page['content'][$currentLanguage] ?? $page['content'][$this->defaultLanguage];
        
        $options = [
            'title' => $page['title'][$currentLanguage] ?? $page['title'][$this->defaultLanguage],
            'description' => $page['description'][$currentLanguage] ?? $page['description'][$this->defaultLanguage],
            'url' => $page['urls'][$currentLanguage],
            'language' => $currentLanguage,
            'keywords' => $page['keywords'][$currentLanguage] ?? []
        ];

        $analysis = $this->seoManager->analyze($content, $options);

        return [
            'meta_tags' => $analysis->getMetaTags(),
            'hreflang_tags' => $this->generateHreflangTags($page['urls']),
            'structured_data' => $this->generateMultiLanguageStructuredData($page, $currentLanguage),
            'language_selector' => $this->generateLanguageSelector($page['urls'], $currentLanguage)
        ];
    }

    private function generateHreflangTags(array $urls): string
    {
        $tags = [];
        
        foreach ($urls as $language => $url) {
            $tags[] = '<link rel="alternate" hreflang="' . $language . '" href="' . $url . '">';
        }
        
        // Add x-default for default language
        if (isset($urls[$this->defaultLanguage])) {
            $tags[] = '<link rel="alternate" hreflang="x-default" href="' . $urls[$this->defaultLanguage] . '">';
        }

        return implode("\n", $tags);
    }

    private function generateMultiLanguageStructuredData(array $page, string $currentLanguage): string
    {
        $schema = [
            '@context' => 'https://schema.org',
            '@type' => 'WebPage',
            'name' => $page['title'][$currentLanguage],
            'description' => $page['description'][$currentLanguage],
            'url' => $page['urls'][$currentLanguage],
            'inLanguage' => $currentLanguage
        ];

        // Add translations
        if (count($page['urls']) > 1) {
            $schema['translationOfWork'] = [];
            foreach ($page['urls'] as $lang => $url) {
                if ($lang !== $currentLanguage) {
                    $schema['translationOfWork'][] = [
                        '@type' => 'WebPage',
                        'name' => $page['title'][$lang] ?? $page['title'][$this->defaultLanguage],
                        'url' => $url,
                        'inLanguage' => $lang
                    ];
                }
            }
        }

        return json_encode($schema, JSON_PRETTY_PRINT);
    }
}

Advanced Schema Implementation

Recipe Schema Example

class RecipeSeoManager
{
    private SeoManager $seoManager;

    public function generateRecipeSeo(array $recipe): array
    {
        $content = $this->buildRecipeHtml($recipe);
        
        $options = [
            'type' => 'recipe',
            'title' => $recipe['name'],
            'description' => $recipe['description'],
            'image' => $recipe['image'],
            'recipe_data' => $recipe
        ];

        $analysis = $this->seoManager->analyze($content, $options);

        return [
            'meta_tags' => $analysis->getMetaTags(),
            'structured_data' => $this->generateRecipeStructuredData($recipe),
            'social_tags' => $this->generateRecipeSocialTags($recipe)
        ];
    }

    private function generateRecipeStructuredData(array $recipe): string
    {
        $schema = [
            '@context' => 'https://schema.org',
            '@type' => 'Recipe',
            'name' => $recipe['name'],
            'description' => $recipe['description'],
            'image' => $this->processRecipeImages($recipe['images']),
            'author' => [
                '@type' => 'Person',
                'name' => $recipe['author']['name']
            ],
            'datePublished' => $recipe['published_at'],
            'prepTime' => $this->formatDuration($recipe['prep_time']),
            'cookTime' => $this->formatDuration($recipe['cook_time']),
            'totalTime' => $this->formatDuration($recipe['total_time']),
            'recipeYield' => $recipe['servings'],
            'recipeCategory' => $recipe['category'],
            'recipeCuisine' => $recipe['cuisine'],
            'keywords' => implode(',', $recipe['keywords'] ?? []),
            'recipeIngredient' => $recipe['ingredients'],
            'recipeInstructions' => $this->formatInstructions($recipe['instructions']),
            'nutrition' => $this->formatNutrition($recipe['nutrition'] ?? [])
        ];

        // Add ratings if available
        if (!empty($recipe['rating'])) {
            $schema['aggregateRating'] = [
                '@type' => 'AggregateRating',
                'ratingValue' => $recipe['rating']['average'],
                'reviewCount' => $recipe['rating']['count']
            ];
        }

        // Add video if available
        if (!empty($recipe['video'])) {
            $schema['video'] = [
                '@type' => 'VideoObject',
                'name' => $recipe['name'] . ' - Video Recipe',
                'description' => $recipe['description'],
                'thumbnailUrl' => $recipe['video']['thumbnail'],
                'contentUrl' => $recipe['video']['url'],
                'uploadDate' => $recipe['video']['upload_date'] ?? $recipe['published_at']
            ];
        }

        return json_encode($schema, JSON_PRETTY_PRINT);
    }

    private function formatInstructions(array $instructions): array
    {
        return array_map(function($instruction, $index) {
            return [
                '@type' => 'HowToStep',
                'position' => $index + 1,
                'text' => $instruction['text'],
                'url' => $instruction['url'] ?? null,
                'image' => $instruction['image'] ?? null
            ];
        }, $instructions, array_keys($instructions));
    }

    private function formatDuration(int $minutes): string
    {
        $hours = floor($minutes / 60);
        $mins = $minutes % 60;
        
        $duration = 'PT';
        if ($hours > 0) {
            $duration .= $hours . 'H';
        }
        if ($mins > 0) {
            $duration .= $mins . 'M';
        }
        
        return $duration;
    }

    private function formatNutrition(array $nutrition): array
    {
        if (empty($nutrition)) {
            return [];
        }

        return [
            '@type' => 'NutritionInformation',
            'calories' => $nutrition['calories'] ?? null,
            'carbohydrateContent' => $nutrition['carbs'] ?? null,
            'proteinContent' => $nutrition['protein'] ?? null,
            'fatContent' => $nutrition['fat'] ?? null,
            'fiberContent' => $nutrition['fiber'] ?? null,
            'sugarContent' => $nutrition['sugar'] ?? null,
            'sodiumContent' => $nutrition['sodium'] ?? null
        ];
    }
}

Performance Optimization Examples

Cached SEO Manager

use Psr\SimpleCache\CacheInterface;

class CachedSeoManager
{
    private SeoManager $seoManager;
    private CacheInterface $cache;
    private int $ttl;

    public function __construct(SeoManager $seoManager, CacheInterface $cache, int $ttl = 3600)
    {
        $this->seoManager = $seoManager;
        $this->cache = $cache;
        $this->ttl = $ttl;
    }

    public function analyze(string $content, array $options = []): SeoAnalysis
    {
        $cacheKey = $this->generateCacheKey($content, $options);
        
        $cached = $this->cache->get($cacheKey);
        if ($cached !== null) {
            return unserialize($cached);
        }

        $analysis = $this->seoManager->analyze($content, $options);
        $this->cache->set($cacheKey, serialize($analysis), $this->ttl);

        return $analysis;
    }

    public function batchAnalyze(array $items): array
    {
        $results = [];
        $uncachedItems = [];
        
        // Check cache for all items
        foreach ($items as $key => $item) {
            $cacheKey = $this->generateCacheKey($item['content'], $item['options']);
            $cached = $this->cache->get($cacheKey);
            
            if ($cached !== null) {
                $results[$key] = unserialize($cached);
            } else {
                $uncachedItems[$key] = $item;
            }
        }
        
        // Process uncached items
        foreach ($uncachedItems as $key => $item) {
            $analysis = $this->seoManager->analyze($item['content'], $item['options']);
            $results[$key] = $analysis;
            
            // Cache the result
            $cacheKey = $this->generateCacheKey($item['content'], $item['options']);
            $this->cache->set($cacheKey, serialize($analysis), $this->ttl);
        }
        
        return $results;
    }

    private function generateCacheKey(string $content, array $options): string
    {
        return 'seo_analysis_' . md5($content . serialize($options));
    }
}

Streaming Content Processor

class StreamingSeoProcessor
{
    private SeoManager $seoManager;
    private int $chunkSize;

    public function __construct(SeoManager $seoManager, int $chunkSize = 100000)
    {
        $this->seoManager = $seoManager;
        $this->chunkSize = $chunkSize;
    }

    public function processLargeContent(string $content): SeoAnalysis
    {
        if (strlen($content) <= $this->chunkSize) {
            return $this->seoManager->analyze($content);
        }

        // Extract head and key content
        $importantContent = $this->extractImportantContent($content);
        
        return $this->seoManager->analyze($importantContent);
    }

    private function extractImportantContent(string $content): string
    {
        $dom = new DOMDocument();
        @$dom->loadHTML($content);
        $xpath = new DOMXPath($dom);

        $important = '';
        
        // Extract head
        $head = $xpath->query('//head')->item(0);
        if ($head) {
            $important .= $dom->saveHTML($head);
        }
        
        // Extract main content areas
        $selectors = [
            '//main',
            '//article',
            '//*[@id="content"]',
            '//*[@class="content"]',
            '//h1 | //h2 | //h3'
        ];
        
        foreach ($selectors as $selector) {
            $elements = $xpath->query($selector);
            foreach ($elements as $element) {
                $important .= $dom->saveHTML($element);
                
                // Stop if we've collected enough content
                if (strlen($important) >= $this->chunkSize) {
                    break 2;
                }
            }
        }
        
        return '<html><head></head><body>' . $important . '</body></html>';
    }
}

These advanced examples demonstrate real-world usage patterns and provide a foundation for implementing comprehensive SEO solutions with the PHP-SEO package.

Clone this wiki locally