php-seo is a modern, AI-powered, framework-agnostic PHP package for automated SEO optimization. It intelligently generates meta tags, titles, descriptions, and alt texts using configurable AI providers or manual patterns, seamlessly integrating with Laravel, Symfony, or any PHP project.
- Intelligent Content Analysis: AI reads and analyzes page content to generate optimal titles, descriptions, and meta tags
- Image Analysis: Automatically generates alt text and titles for images by analyzing context
- Social Media Optimization: Generates platform-specific meta tags (Open Graph, Twitter Cards, etc.)
- Multi-Provider Support: Integration with popular AI models (GPT-4/5, Claude, Gemini, Grok, Ollama)
- Pattern-Based Generation: Generate titles and descriptions using configurable patterns
- Manual Override: Full manual control over all SEO elements
- Fallback Systems: Graceful degradation when AI services are unavailable
- Template-Based: Use predefined templates for consistent SEO across pages
- Laravel: Native service provider, facades, config publishing, middleware
- Symfony: Bundle integration with services and configuration
- Generic PHP: Framework-agnostic core that works with any PHP project
- Type-safe: Full PHP 8.2+ type declarations and strict types
- Extensible: Plugin architecture for custom analyzers and generators
- High Performance: Optimized for speed with caching and lazy loading
- 100% Test Pass Rate: Comprehensive test suite with 405 passing tests using Pest
- Type-safe: Full PHP 8.2+ type declarations and strict types
- π Installation
- π‘ Usage Examples
- βοΈ Configuration
- π€ AI Providers
- π§ͺ Testing & Development
- π€ Contributing
- π¬ Discussions
- π Security Policy
- π Support & Funding
- π License
Install via Composer:
composer require rumenx/php-seo- PHP 8.2 or higher
- ext-json
- ext-curl
// In your controller
use Rumenx\PhpSeo\SeoManager;
public function show(Post $post, SeoManager $seo)
{
$content = view('posts.content', compact('post'))->render();
$seoData = $seo->analyze($content, [
'title' => $post->title,
'url' => request()->url(),
'image' => $post->featured_image,
'author' => $post->author->name,
'published_at' => $post->published_at->toISOString(),
])->generateAll();
return view('posts.show', compact('post', 'seoData'));
}@extends('layouts.app')
@section('head')
{!! app('seo')->renderMetaTags($seoData) !!}
@endsection
@section('content')
<!-- Your content here -->
@endsectionuse Rumenx\PhpSeo\Facades\Seo;
// Quick generation
$title = Seo::analyze($content)->generateTitle();
$description = Seo::generateDescription();
$metaTags = Seo::generateMetaTags();
// Complete SEO data
$seoData = Seo::analyze($content, $metadata)->generateAll();// In app/Http/Kernel.php
protected $routeMiddleware = [
'seo' => \Rumenx\PhpSeo\Integrations\Laravel\SeoMiddleware::class,
];
// In your routes
Route::get('/posts/{post}', [PostController::class, 'show'])
->middleware('seo');use Rumenx\PhpSeo\SeoManager;
use Symfony\Component\HttpFoundation\Response;
class PostController extends AbstractController
{
public function show(Post $post, SeoManager $seo): Response
{
$content = $this->renderView('post/content.html.twig', ['post' => $post]);
$seoData = $seo->analyze($content, [
'title' => $post->getTitle(),
'url' => $this->generateUrl('post_show', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL),
'image' => $post->getFeaturedImage(),
'author' => $post->getAuthor()->getName(),
])->generateAll();
return $this->render('post/show.html.twig', [
'post' => $post,
'seo_data' => $seoData,
]);
}
}{% extends 'base.html.twig' %}
{% block head %}
{{ seo_meta_tags(seo_data)|raw }}
{% endblock %}
{% block body %}
<!-- Your content here -->
{% endblock %}require 'vendor/autoload.php';
use Rumenx\PhpSeo\SeoManager;
use Rumenx\PhpSeo\Config\SeoConfig;
// Basic usage
$seo = new SeoManager();
$content = file_get_contents('page-content.html');
$seoData = $seo->analyze($content, [
'title' => 'My Page Title',
'url' => 'https://example.com/page',
])->generateAll();
// Output meta tags
echo $seo->renderMetaTags($seoData);
// With custom configuration
$config = new SeoConfig([
'title' => [
'pattern' => '{title} - {site_name}',
'site_name' => 'My Website',
'max_length' => 55,
],
'mode' => 'ai',
'ai' => [
'provider' => 'openai',
'api_key' => $_ENV['OPENAI_API_KEY'],
],
]);
$seo = new SeoManager($config);
$optimizedTitle = $seo->analyze($content)->generateTitle();Publish the configuration file:
php artisan vendor:publish --provider="Rumenx\PhpSeo\Integrations\Laravel\SeoServiceProvider"Edit config/seo.php:
return [
'mode' => 'hybrid', // 'ai', 'manual', 'hybrid'
'ai' => [
'provider' => 'openai',
'api_key' => env('SEO_AI_API_KEY'),
'model' => 'gpt-4-turbo-preview',
],
'title' => [
'pattern' => '{title} | {site_name}',
'site_name' => env('APP_NAME'),
'max_length' => 60,
],
// ... more configuration
];# Basic settings
SEO_ENABLED=true
SEO_MODE=hybrid
SEO_CACHE_ENABLED=true
# AI Provider
SEO_AI_PROVIDER=openai
SEO_AI_API_KEY=your-api-key-here
SEO_AI_MODEL=gpt-4-turbo-preview
# Title settings
SEO_TITLE_PATTERN="{title} | {site_name}"
SEO_SITE_NAME="My Website"
# Social media
SEO_OG_SITE_NAME="My Website"
SEO_TWITTER_SITE="@mywebsite"$config = new SeoConfig([
'ai' => [
'provider' => 'openai',
'api_key' => 'your-openai-api-key',
'model' => 'gpt-4-turbo-preview',
],
]);$config = new SeoConfig([
'ai' => [
'provider' => 'anthropic',
'api_key' => 'your-anthropic-api-key',
'model' => 'claude-3-sonnet-20240229',
],
]);$config = new SeoConfig([
'ai' => [
'provider' => 'google',
'api_key' => 'your-google-api-key',
'model' => 'gemini-pro',
],
]);$config = new SeoConfig([
'ai' => [
'provider' => 'ollama',
'api_url' => 'http://localhost:11434',
'model' => 'llama2',
],
]);$config = new SeoConfig([
'ai' => [
'provider' => 'openai',
'api_key' => 'primary-key',
'fallback_providers' => [
['provider' => 'anthropic', 'api_key' => 'backup-key'],
['provider' => 'ollama', 'api_url' => 'http://localhost:11434'],
],
],
]);use Rumenx\PhpSeo\Contracts\AnalyzerInterface;
class CustomContentAnalyzer implements AnalyzerInterface
{
public function analyze(string $content, array $metadata = []): array
{
// Your custom analysis logic
return [
'custom_data' => $this->extractCustomData($content),
// ... other data
];
}
public function supports(string $contentType): bool
{
return $contentType === 'custom/format';
}
}
// Use your custom analyzer
$seo = new SeoManager(
config: $config,
contentAnalyzer: new CustomContentAnalyzer()
);use Rumenx\PhpSeo\Contracts\GeneratorInterface;
class CustomTitleGenerator implements GeneratorInterface
{
public function generate(array $pageData): string
{
// Your custom generation logic
return $this->createCustomTitle($pageData);
}
public function generateCustom(mixed $customInput, array $pageData = []): string
{
// Handle custom input
return $this->processCustomTitle($customInput, $pageData);
}
public function supports(string $type): bool
{
return $type === 'title';
}
}$posts = Post::all();
$seoResults = [];
foreach ($posts as $post) {
$content = $post->getContent();
$metadata = [
'title' => $post->getTitle(),
'url' => $post->getUrl(),
'author' => $post->getAuthor(),
];
$seoResults[$post->getId()] = $seo
->analyze($content, $metadata)
->generateAll();
}# Run all tests (405 tests, 1037 assertions - 100% passing! β
)
composer test
# Run tests with coverage
composer test-coverage
# Generate HTML coverage report
composer test-coverage-html
# Run specific test
./vendor/bin/pest tests/Unit/SeoManagerTest.php
# Run specific test group
./vendor/bin/pest --filter="OllamaProvider"
# Run with verbose output
./vendor/bin/pest --verboseThe package maintains 100% test pass rate with comprehensive test coverage:
- β 405 passing tests across all components
- β 1037 assertions ensuring code quality
- β Unit tests for all core functionality
- β Integration tests for Laravel and Symfony
- β AI Provider tests for OpenAI, Anthropic, Google, xAI, and Ollama
- β Generator tests for titles, descriptions, and meta tags
- β Analyzer tests for content processing
- β Validator tests for response validation
# Check coding standards
composer style
# Fix coding standards
composer style-fix
# Run static analysis
composer analyze
# Run all quality checks
composer quality- Configuration Reference
- AI Integration Guide
- Laravel Examples
- Symfony Examples
- Plain PHP Examples
- Basic Examples
- Home
We welcome contributions! Please see our Contributing Guide for details.
- π Report issues
- π‘ Request features
- π§ Submit pull requests
If you discover a security vulnerability, please review our Security Policy for responsible disclosure guidelines.
If you find this package helpful, consider:
- β Starring the repository
- π Supporting development
- π Reporting issues
- π€ Contributing improvements
MIT License. Please see the license file for more information.
php-seo is created and maintained by Rumen Damyanov. It's inspired by the success of php-sitemap and aims to bring the same level of quality and ease-of-use to SEO optimization.
This package is part of a multi-language SEO ecosystem:
-
@rumenx/seo - JavaScript/TypeScript SEO package for Node.js and browsers
- π¦ NPM Package
- π» GitHub Repository
- β‘ Framework-agnostic with React, Vue, Angular integrations
- π Works in both Node.js and browser environments
-
php-seo (this package) - PHP SEO package for Laravel, Symfony, and any PHP project
- π PHP 8.2+ with full type safety
- π€ AI-powered content generation
- ποΈ Framework-agnostic with Laravel/Symfony integrations
-
go-seo (planned) - Go SEO package
- π High-performance SEO optimization for Go applications
- Coming soon!
All packages share similar APIs and best practices, making it easy to work across different tech stacks.
- php-chatbot - AI powered chatbot package
- php-sitemap - Framework-agnostic sitemap generation
- php-feed - Framework-agnostic rss feed generation
- php-calendar - Framework-agnostic calendar package
- php-vcard - Framework-agnostic vcard generation
- More projects coming soon!
Framework-agnostic AI-powered SEO optimization for modern PHP applications.