PHPackages                             juampi92/test-seo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. juampi92/test-seo

ActiveLibrary[Testing &amp; Quality](/categories/testing)

juampi92/test-seo
=================

Easy way to test your SEO

v1.9(4mo ago)26348.5k↓50.1%5MITPHPPHP ^8.0.2CI passing

Since Aug 28Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/juampi92/test-seo)[ Packagist](https://packagist.org/packages/juampi92/test-seo)[ Docs](https://github.com/juampi92/test-seo)[ RSS](/packages/juampi92-test-seo/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (9)Dependencies (12)Versions (12)Used By (0)

Test SEO
========

[](#test-seo)

[![Latest Version on Packagist](https://camo.githubusercontent.com/ab00719ca3f00bdf8918c58aa84d274a89a95bb6696d070682f86a810a20cb75/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a75616d706939322f746573742d73656f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/juampi92/test-seo)[![GitHub Tests Action Status](https://camo.githubusercontent.com/58824bb24385565d46f837941fee01a5d7f75abcdc59487bc32c42c766fb939a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6a75616d706939322f746573742d73656f2f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/juampi92/test-seo/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/0c2d09f004badcf7dc2c9ada25c84bb085e8aafe1c2540b727cbda7d95eeb16e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6a75616d706939322f746573742d73656f2f70696e742e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652d7374796c65267374796c653d666c61742d737175617265)](https://github.com/juampi92/test-seo/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/2107374a5c957d1aafe76dcea1b2d976b337b24283b0a644ce0f933e3b77c4f2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a75616d706939322f746573742d73656f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/juampi92/test-seo)

An easy-to-use package for testing SEO. The package allows you to extract SEO tags from a given HTML and verify that the SEO structure is correct.

- [Installation](#instalation)
- [Usage](#usage)
    - [PHPUnit](#phpunit)
    - [Laravel](#laravel)
    - [Pest](#pest)
- [API](#seo-data)
    - [SEO Data](#seo-data)
    - [Assertions](#sssertions)
- [Snapshot testing](#snapshots)

---

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require juampi92/test-seo --dev
```

Usage
-----

[](#usage)

```
// Create TestSEO instance using the response:
$seo = new TestSEO($htmlResponse);

// Perform assertions:
$seo->assertTitleEndsWith(' - My Website');

// Assert the data yourself:
$this->assertEquals(
    'My title - My Website',
    $seo->data->title()
);
```

Look at the following examples using **PHPUnit**, **Laravel**, and **Pest**.

### PHPUnit

[](#phpunit)

```
public function testLandingPageSEO()
{
    // Arrange
    // ...

    // Act
    $response = $client->get('/')->send();

    // Assert
    $this->assertEquals(200, $response->getStatusCode());
    $html = json_decode($response->getBody(true), true);

    $seo = new TestSEO($html);

    // Assert
    $seo
        ->assertTitleEndsWith(' - My Website')
        ->assertCanonicalIs('https://www.mywebsite.com/');
}
```

### Laravel

[](#laravel)

```
public function test_landing_page_SEO()
{
    // Arrange
    // ...

    // Act
    $response = $this->get('/');

    // Assert
    $response->assertStatus(200);

    $seo = new TestSEO($response->getContent());

    $seo
        ->assertTitleEndsWith(' - My Website')
        ->assertCanonicalIs('https://www.mywebsite.com/');
}
```

### Pest

[](#pest)

```
test('landing page SEO tags', function () {
    // Arrange
    // ...

    // Act
    $response = get('/')->assertStatus(200);

    $seo = new TestSEO($response->getContent());

    // Assert
    expect($seo->data)
        ->title()->toEndWith(' - My Website')
        ->description()->toBe('This is my description')
        ->canonical()->not()->toBeNull()
        ->robots()->index()->toBeTrue()
        ->robots()->nofollow()->toBeTrue();
});
```

SEO Data
--------

[](#seo-data)

You can access the SEO Data yourself by accessing the public property `TestSEO->data`. Here are the available methods:

MethodReturnsDescription`title()``?string``{this}``description()``?string````image()``?Url` [🔍](https://github.com/spatie/url)```robots()``Robots` [🔍](https://github.com/juampi92/test-seo/blob/main/src/Tags/Robots.php)```canonical()``?Url` [🔍](https://github.com/spatie/url)```prev()``?Url` [🔍](https://github.com/spatie/url)```next()``?Url` [🔍](https://github.com/spatie/url)```openGraph()``TagCollection` [🔍](https://github.com/juampi92/test-seo/blob/main/src/Tags/TagCollection.php)```twitter()``TagCollection` [🔍](https://github.com/juampi92/test-seo/blob/main/src/Tags/TagCollection.php)```alternateHrefLang()``AlternateHrefLangCollection` [🔍](https://github.com/juampi92/test-seo/blob/main/src/Tags/AlternateHrefLangCollection.php)```images()``array`All images in the page. ```h1s()``array`All H1 in the page. `{this}``h2s()``array`All H2 in the page. `{this}``charset()``?string```The SEOData class is **Macroable**, so feel free to extend it yourself.

Assertions
----------

[](#assertions)

MethodNotes`assertCanonicalIs(string $expected)``assertCanonicalIsEmpty()``assertRobotsIsEmpty()``assertRobotsIsNoIndexNoFollow()`Checks that the robots are `noindex, nofollo` or `none``assertPaginationIsEmpty()``prev` and `next` are both missing.`assertAlternateHrefLangIsEmpty()``assertTitleIs(string $expected)``assertTitleContains(string $expected)``assertTitleEndsWith(string $expected)``assertDescriptionIs(string $expected)``assertThereIsOnlyOneH1()`Make sure there is only one H1 in the entire website.`assertAllImagesHaveAltText()`Make sure all images have an `alt="..."`Suggest your own!These assertions can help devs to follow the best SEO practices. Make a PR if you think some are missing!Snapshots
---------

[](#snapshots)

When it comes to SEO, a snapshot test is a great way to ensure nothing has been changed by accident.

Here is an example:

```
$seo = new TestSEO($response->getContent(), snapshotSerializer: null);

$json = json_encode($seo);
```

By default, the SEO tags are serialized using the `SimpleSerializer`. Make your own serializer by implementing the `SnapshotSerializer` interface:

```
$seo = new TestSEO($response->getContent(), new MyCustomSerializer());

$json = json_encode($seo);
```

### Pest Example

[](#pest-example)

```
use function Spatie\Snapshots\{assertMatchesSnapshot, assertMatchesJsonSnapshot};
use Juampi92\TestSEO\TestSEO;

test('landing page SEO', function () {
    $response = $this->get('/');

    $response->assertStatus(200);

    $seo = new TestSEO($response->getContent());

    assertMatchesJsonSnapshot(json_encode($seo));
});
```

**Note:** this example requires `spatie/pest-plugin-snapshots`.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Credits
-------

[](#credits)

- [Juan Pablo Barreto](https://github.com/juampi92)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance74

Regular maintenance activity

Popularity45

Moderate usage in the ecosystem

Community13

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 93.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~145 days

Recently: every ~276 days

Total

10

Last Release

146d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1f8d31c9bb6d7862e21aac7af0f7b2615dc06485b4c30b19b8d9fdffaa42c712?d=identicon)[juampi92](/maintainers/juampi92)

---

Top Contributors

[![juampi92](https://avatars.githubusercontent.com/u/2080215?v=4)](https://github.com/juampi92 "juampi92 (46 commits)")[![canvural](https://avatars.githubusercontent.com/u/1574232?v=4)](https://github.com/canvural "canvural (2 commits)")[![bonsi](https://avatars.githubusercontent.com/u/1137656?v=4)](https://github.com/bonsi "bonsi (1 commits)")

---

Tags

php8phpunitseotestingphptestingphpunitseo

###  Code Quality

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/juampi92-test-seo/health.svg)

```
[![Health](https://phpackages.com/badges/juampi92-test-seo/health.svg)](https://phpackages.com/packages/juampi92-test-seo)
```

###  Alternatives

[brianium/paratest

Parallel testing for PHP

2.5k142.8M1.1k](/packages/brianium-paratest)[drupal/core-dev

require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.

2023.2M367](/packages/drupal-core-dev)[robiningelbrecht/phpunit-pretty-print

Prettify PHPUnit output

77598.4k18](/packages/robiningelbrecht-phpunit-pretty-print)[robiningelbrecht/phpunit-coverage-tools

PHPUnit coverage tools

17172.4k60](/packages/robiningelbrecht-phpunit-coverage-tools)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
