SEO Tools for Laravel

Overview

SEOTools - SEO Tools for Laravel and Lumen


SEOTools is a package for Laravel 5.8+ and Lumen that provides helpers for some common SEO techniques.

Current Build Status

Build Status Code Climate

Statistics

Latest Stable Version Total Downloads Latest Unstable Version License

For license information check the LICENSE-file.

Features

Installation

1 - Dependency

The first step is using composer to install the package and automatically update your composer.json file, you can do this by running:

composer require artesaos/seotools

Note: If you are using Laravel 5.5, the steps 2 and 3, for providers and aliases, are unnecessaries. SEOTools supports Laravel new Package Discovery.

2 - Provider

You need to update your application configuration in order to register the package so it can be loaded by Laravel, just update your config/app.php file adding the following code at the end of your 'providers' section:

config/app.php

<?php

return [
    // ...
    'providers' => [
        Artesaos\SEOTools\Providers\SEOToolsServiceProvider::class,
        // ...
    ],
    // ...
];

Lumen

Go to /bootstrap/app.php file and add this line:

<?php
// ...

$app = new Laravel\Lumen\Application(
    dirname(__DIR__)
);

// ...

$app->register(Artesaos\SEOTools\Providers\SEOToolsServiceProvider::class);

// ...

return $app;

3 - Facades

Note: facades are not supported in Lumen.

You may get access to the SEO tool services using following facades:

  • Artesaos\SEOTools\Facades\SEOMeta
  • Artesaos\SEOTools\Facades\OpenGraph
  • Artesaos\SEOTools\Facades\TwitterCard
  • Artesaos\SEOTools\Facades\JsonLd
  • Artesaos\SEOTools\Facades\JsonLdMulti
  • Artesaos\SEOTools\Facades\SEOTools

You can setup a short-version aliases for these facades in your config/app.php file. For example:

<?php

return [
    // ...
    'aliases' => [
        'SEOMeta'       => Artesaos\SEOTools\Facades\SEOMeta::class,
        'OpenGraph'     => Artesaos\SEOTools\Facades\OpenGraph::class,
        'Twitter'       => Artesaos\SEOTools\Facades\TwitterCard::class,
        'JsonLd'        => Artesaos\SEOTools\Facades\JsonLd::class,
        'JsonLdMulti'   => Artesaos\SEOTools\Facades\JsonLdMulti::class,
        // or
        'SEO' => Artesaos\SEOTools\Facades\SEOTools::class,
        // ...
    ],
    // ...
];

4 Configuration

Publish config

In your terminal type

php artisan vendor:publish

or

php artisan vendor:publish --provider="Artesaos\SEOTools\Providers\SEOToolsServiceProvider"

Lumen does not support this command, for it you should copy the file src/resources/config/seotools.php to config/seotools.php of your project

In seotools.php configuration file you can determine the properties of the default values and some behaviors.

seotools.php

  • meta
  • defaults - What values are displayed if not specified any value for the page display. If the value is false, nothing is displayed.
  • webmaster - Are the settings of tags values for major webmaster tools. If you are null nothing is displayed.
  • opengraph
  • defaults - Are the properties that will always be displayed and when no other value is set instead. You can add additional tags that are not included in the original configuration file.
  • twitter
  • defaults - Are the properties that will always be displayed and when no other value is set instead. You can add additional tags that are not included in the original configuration file.
  • json-ld
  • defaults - Are the properties that will always be displayed and when no other value is set instead. You can add additional tags that are not included in the original configuration file.

Usage

Lumen Usage

Note: facades are not supported in Lumen.

<?php

$seotools = app('seotools');
$metatags = app('seotools.metatags');
$twitter = app('seotools.twitter');
$opengraph = app('seotools.opengraph');
$jsonld = app('seotools.json-ld');
$jsonldMulti = app('seotools.json-ld-multi');

// The behavior is the same as the facade

echo app('seotools')->generate();

Meta tags Generator

With SEOMeta you can create meta tags to the head

Opengraph tags Generator

With OpenGraph you can create OpenGraph tags to the head

Twitter for Twitter Cards tags Generator

With Twitter you can create OpenGraph tags to the head

In your controller

<?php

namespace App\Http\Controllers;

use Artesaos\SEOTools\Facades\SEOMeta;
use Artesaos\SEOTools\Facades\OpenGraph;
use Artesaos\SEOTools\Facades\TwitterCard;
use Artesaos\SEOTools\Facades\JsonLd;
// OR with multi
use Artesaos\SEOTools\Facades\JsonLdMulti;

// OR
use Artesaos\SEOTools\Facades\SEOTools;

class CommomController extends Controller
{
    public function index()
    {
        SEOMeta::setTitle('Home');
        SEOMeta::setDescription('This is my page description');
        SEOMeta::setCanonical('https://codecasts.com.br/lesson');

        OpenGraph::setDescription('This is my page description');
        OpenGraph::setTitle('Home');
        OpenGraph::setUrl('http://current.url.com');
        OpenGraph::addProperty('type', 'articles');

        TwitterCard::setTitle('Homepage');
        TwitterCard::setSite('@LuizVinicius73');

        JsonLd::setTitle('Homepage');
        JsonLd::setDescription('This is my page description');
        JsonLd::addImage('https://codecasts.com.br/img/logo.jpg');

        // OR

        SEOTools::setTitle('Home');
        SEOTools::setDescription('This is my page description');
        SEOTools::opengraph()->setUrl('http://current.url.com');
        SEOTools::setCanonical('https://codecasts.com.br/lesson');
        SEOTools::opengraph()->addProperty('type', 'articles');
        SEOTools::twitter()->setSite('@LuizVinicius73');
        SEOTools::jsonLd()->addImage('https://codecasts.com.br/img/logo.jpg');

        $posts = Post::all();

        return view('myindex', compact('posts'));
    }

    public function show($id)
    {
        $post = Post::find($id);

        SEOMeta::setTitle($post->title);
        SEOMeta::setDescription($post->resume);
        SEOMeta::addMeta('article:published_time', $post->published_date->toW3CString(), 'property');
        SEOMeta::addMeta('article:section', $post->category, 'property');
        SEOMeta::addKeyword(['key1', 'key2', 'key3']);

        OpenGraph::setDescription($post->resume);
        OpenGraph::setTitle($post->title);
        OpenGraph::setUrl('http://current.url.com');
        OpenGraph::addProperty('type', 'article');
        OpenGraph::addProperty('locale', 'pt-br');
        OpenGraph::addProperty('locale:alternate', ['pt-pt', 'en-us']);

        OpenGraph::addImage($post->cover->url);
        OpenGraph::addImage($post->images->list('url'));
        OpenGraph::addImage(['url' => 'http://image.url.com/cover.jpg', 'size' => 300]);
        OpenGraph::addImage('http://image.url.com/cover.jpg', ['height' => 300, 'width' => 300]);
        
        JsonLd::setTitle($post->title);
        JsonLd::setDescription($post->resume);
        JsonLd::setType('Article');
        JsonLd::addImage($post->images->list('url'));

        // OR with multi

        JsonLdMulti::setTitle($post->title);
        JsonLdMulti::setDescription($post->resume);
        JsonLdMulti::setType('Article');
        JsonLdMulti::addImage($post->images->list('url'));
        if(! JsonLdMulti::isEmpty()) {
            JsonLdMulti::newJsonLd();
            JsonLdMulti::setType('WebPage');
            JsonLdMulti::setTitle('Page Article - '.$post->title);
        }

        // Namespace URI: http://ogp.me/ns/article#
        // article
        OpenGraph::setTitle('Article')
            ->setDescription('Some Article')
            ->setType('article')
            ->setArticle([
                'published_time' => 'datetime',
                'modified_time' => 'datetime',
                'expiration_time' => 'datetime',
                'author' => 'profile / array',
                'section' => 'string',
                'tag' => 'string / array'
            ]);

        // Namespace URI: http://ogp.me/ns/book#
        // book
        OpenGraph::setTitle('Book')
            ->setDescription('Some Book')
            ->setType('book')
            ->setBook([
                'author' => 'profile / array',
                'isbn' => 'string',
                'release_date' => 'datetime',
                'tag' => 'string / array'
            ]);

        // Namespace URI: http://ogp.me/ns/profile#
        // profile
        OpenGraph::setTitle('Profile')
             ->setDescription('Some Person')
            ->setType('profile')
            ->setProfile([
                'first_name' => 'string',
                'last_name' => 'string',
                'username' => 'string',
                'gender' => 'enum(male, female)'
            ]);

        // Namespace URI: http://ogp.me/ns/music#
        // music.song
        OpenGraph::setType('music.song')
            ->setMusicSong([
                'duration' => 'integer',
                'album' => 'array',
                'album:disc' => 'integer',
                'album:track' => 'integer',
                'musician' => 'array'
            ]);

        // music.album
        OpenGraph::setType('music.album')
            ->setMusicAlbum([
                'song' => 'music.song',
                'song:disc' => 'integer',
                'song:track' => 'integer',
                'musician' => 'profile',
                'release_date' => 'datetime'
            ]);

         //music.playlist
        OpenGraph::setType('music.playlist')
            ->setMusicPlaylist([
                'song' => 'music.song',
                'song:disc' => 'integer',
                'song:track' => 'integer',
                'creator' => 'profile'
            ]);

        // music.radio_station
        OpenGraph::setType('music.radio_station')
            ->setMusicRadioStation([
                'creator' => 'profile'
            ]);

        // Namespace URI: http://ogp.me/ns/video#
        // video.movie
        OpenGraph::setType('video.movie')
            ->setVideoMovie([
                'actor' => 'profile / array',
                'actor:role' => 'string',
                'director' => 'profile /array',
                'writer' => 'profile / array',
                'duration' => 'integer',
                'release_date' => 'datetime',
                'tag' => 'string / array'
            ]);

        // video.episode
        OpenGraph::setType('video.episode')
            ->setVideoEpisode([
                'actor' => 'profile / array',
                'actor:role' => 'string',
                'director' => 'profile /array',
                'writer' => 'profile / array',
                'duration' => 'integer',
                'release_date' => 'datetime',
                'tag' => 'string / array',
                'series' => 'video.tv_show'
            ]);

        // video.tv_show
        OpenGraph::setType('video.tv_show')
            ->setVideoTVShow([
                'actor' => 'profile / array',
                'actor:role' => 'string',
                'director' => 'profile /array',
                'writer' => 'profile / array',
                'duration' => 'integer',
                'release_date' => 'datetime',
                'tag' => 'string / array'
            ]);

        // video.other
        OpenGraph::setType('video.other')
            ->setVideoOther([
                'actor' => 'profile / array',
                'actor:role' => 'string',
                'director' => 'profile /array',
                'writer' => 'profile / array',
                'duration' => 'integer',
                'release_date' => 'datetime',
                'tag' => 'string / array'
            ]);

        // og:video
        OpenGraph::addVideo('http://example.com/movie.swf', [
                'secure_url' => 'https://example.com/movie.swf',
                'type' => 'application/x-shockwave-flash',
                'width' => 400,
                'height' => 300
            ]);

        // og:audio
        OpenGraph::addAudio('http://example.com/sound.mp3', [
                'secure_url' => 'https://secure.example.com/sound.mp3',
                'type' => 'audio/mpeg'
            ]);

        // og:place
        OpenGraph::setTitle('Place')
             ->setDescription('Some Place')
            ->setType('place')
            ->setPlace([
                'location:latitude' => 'float',
                'location:longitude' => 'float',
            ]);

        return view('myshow', compact('post'));
    }
}

SEOTrait

<?php

namespace App\Http\Controllers;

use Artesaos\SEOTools\Traits\SEOTools as SEOToolsTrait;

class CommomController extends Controller
{
    use SEOToolsTrait;

    public function index()
    {
        $this->seo()->setTitle('Home');
        $this->seo()->setDescription('This is my page description');
        $this->seo()->opengraph()->setUrl('http://current.url.com');
        $this->seo()->opengraph()->addProperty('type', 'articles');
        $this->seo()->twitter()->setSite('@LuizVinicius73');
        $this->seo()->jsonLd()->setType('Article');

        $posts = Post::all();

        return view('myindex', compact('posts'));
    }
}

In Your View

Pro Tip: Pass the parameter true to get minified code and reduce filesize.

<html>
<head>
    {!! SEOMeta::generate() !!}
    {!! OpenGraph::generate() !!}
    {!! Twitter::generate() !!}
    {!! JsonLd::generate() !!}
    // OR with multi
    {!! JsonLdMulti::generate() !!}

    <!-- OR -->
    {!! SEO::generate() !!}

    <!-- MINIFIED -->
    {!! SEO::generate(true) !!}

    <!-- LUMEN -->
    {!! app('seotools')->generate() !!}
</head>
<body>

</body>
</html>
<html>
<head>
    <title>Title - Over 9000 Thousand!</title>
    <meta name='description' itemprop='description' content='description...' />
    <meta name='keywords' content='key1, key2, key3' />
    <meta property='article:published_time' content='2015-01-31T20:30:11-02:00' />
    <meta property='article:section' content='news' />

    <meta property="og:description"content="description..." />
    <meta property="og:title"content="Title" />
    <meta property="og:url"content="http://current.url.com" />
    <meta property="og:type"content="article" />
    <meta property="og:locale"content="pt-br" />
    <meta property="og:locale:alternate"content="pt-pt" />
    <meta property="og:locale:alternate"content="en-us" />
    <meta property="og:site_name"content="name" />
    <meta property="og:image"content="http://image.url.com/cover.jpg" />
    <meta property="og:image"content="http://image.url.com/img1.jpg" />
    <meta property="og:image"content="http://image.url.com/img2.jpg" />
    <meta property="og:image"content="http://image.url.com/img3.jpg" />
    <meta property="og:image:url"content="http://image.url.com/cover.jpg" />
    <meta property="og:image:size"content="300" />

    <meta name="twitter:card"content="summary" />
    <meta name="twitter:title"content="Title" />
    <meta name="twitter:site"content="@LuizVinicius73" />
    
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","name":"Title - Over 9000 Thousand!"}</script>
    <!-- OR with multi -->
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","name":"Title - Over 9000 Thousand!"}</script>
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Title - Over 9000 Thousand!"}</script>
</head>
<body>

</body>
</html>

API (SEOMeta)

<?php

use Artesaos\SEOTools\Facades\SEOMeta;

SEOMeta::addKeyword($keyword);
SEOMeta::addMeta($meta, $value = null, $name = 'name');
SEOMeta::addAlternateLanguage($lang, $url);
SEOMeta::addAlternateLanguages(array $languages);
SEOMeta::setTitleSeparator($separator);
SEOMeta::setTitle($title);
SEOMeta::setTitleDefault($default);
SEOMeta::setDescription($description);
SEOMeta::setKeywords($keywords);
SEOMeta::setRobots($robots);
SEOMeta::setCanonical($url);
SEOMeta::setPrev($url);
SEOMeta::setNext($url);
SEOMeta::removeMeta($key);

// You can chain methods
SEOMeta::setTitle($title)
            ->setDescription($description)
            ->setKeywords($keywords)
            ->addKeyword($keyword)
            ->addMeta($meta, $value);

// Retrieving data
SEOMeta::getTitle();
SEOMeta::getTitleSession();
SEOMeta::getTitleSeparator();
SEOMeta::getKeywords();
SEOMeta::getDescription();
SEOMeta::getCanonical($url);
SEOMeta::getPrev($url);
SEOMeta::getNext($url);
SEOMeta::getRobots();
SEOMeta::reset();

SEOMeta::generate();

API (OpenGraph)

<?php

use Artesaos\SEOTools\Facades\OpenGraph;

OpenGraph::addProperty($key, $value); // value can be string or array
OpenGraph::addImage($url); // add image url
OpenGraph::addImages($url); // add an array of url images
OpenGraph::setTitle($title); // define title
OpenGraph::setDescription($description);  // define description
OpenGraph::setUrl($url); // define url
OpenGraph::setSiteName($name); //define site_name

// You can chain methods
OpenGraph::addProperty($key, $value)
            ->addImage($url)
            ->addImages($url)
            ->setTitle($title)
            ->setDescription($description)
            ->setUrl($url)
            ->setSiteName($name);

// Generate html tags
OpenGraph::generate();

API (TwitterCard)

<?php

use Artesaos\SEOTools\Facades\TwitterCard;

TwitterCard::addValue($key, $value); // value can be string or array
TwitterCard::setType($type); // type of twitter card tag
TwitterCard::setTitle($type); // title of twitter card tag
TwitterCard::setSite($type); // site of twitter card tag
TwitterCard::setDescription($type); // description of twitter card tag
TwitterCard::setUrl($type); // url of twitter card tag
TwitterCard::setImage($url); // add image url

// You can chain methods
TwitterCard::addValue($key, $value)
            ->setType($type)
            ->setImage($url)
            ->setTitle($title)
            ->setDescription($description)
            ->setUrl($url)
            ->setSite($name);

// Generate html tags
TwitterCard::generate();

API (JsonLd)

<?php

use Artesaos\SEOTools\Facades\JsonLd;

JsonLd::addValue($key, $value); // value can be string or array
JsonLd::setType($type); // type of twitter card tag
JsonLd::setTitle($type); // title of twitter card tag
JsonLd::setSite($type); // site of twitter card tag
JsonLd::setDescription($type); // description of twitter card tag
JsonLd::setUrl($type); // url of twitter card tag
JsonLd::setImage($url); // add image url

// You can chain methods
JsonLd::addValue($key, $value)
    ->setType($type)
    ->setImage($url)
    ->setTitle($title)
    ->setDescription($description)
    ->setUrl($url)
    ->setSite($name);

// Generate html tags
JsonLd::generate();

API (JsonLdMulti)

<?php

use Artesaos\SEOTools\Facades\JsonLdMulti;

JsonLdMulti::newJsonLd(); // create a new JsonLd group
JsonLdMulti::isEmpty(); // check if the current JsonLd group is empty
JsonLdMulti::select($index); // choose the JsonLd group that will be edited by the methods below
JsonLdMulti::addValue($key, $value); // value can be string or array
JsonLdMulti::setType($type); // type of twitter card tag
JsonLdMulti::setTitle($type); // title of twitter card tag
JsonLdMulti::setSite($type); // site of twitter card tag
JsonLdMulti::setDescription($type); // description of twitter card tag
JsonLdMulti::setUrl($type); // url of twitter card tag
JsonLdMulti::setImage($url); // add image url

// You can chain methods
JsonLdMulti::addValue($key, $value)
    ->setType($type)
    ->setImage($url)
    ->setTitle($title)
    ->setDescription($description)
    ->setUrl($url)
    ->setSite($name);
// You can add an other group
if(! JsonLdMulti::isEmpty()) {
    JsonLdMulti::newJsonLd()
        ->setType($type)
        ->setImage($url)
        ->setTitle($title)
        ->setDescription($description)
        ->setUrl($url)
        ->setSite($name);
}
// Generate html tags
JsonLdMulti::generate();
// You will have retrieve <script content="application/ld+json"/>

API (SEO)

Facilitates access to all the SEO Providers

<?php

use Artesaos\SEOTools\Facades\SEOTools;

SEOTools::metatags();
SEOTools::twitter();
SEOTools::opengraph();
SEOTools::jsonLd();

SEOTools::setTitle($title);
SEOTools::getTitle($session = false);
SEOTools::setDescription($description);
SEOTools::setCanonical($url);
SEOTools::addImages($urls);

Missing Features

There are many SEO-related features, which you may need for your project. While this package provides support for the basic ones, other are out of its scope. You'll have to use separated packages fot their integration.

SiteMap

This package does not support sitemap files generation. Please consider usage one of the following packages for it:

URL Trailing Slash

This package does not handle URL consistency regardless absence or presence of the slash symbol at its end. Please consider usage one of the following packages if you need it:

Microdata Markup

This package does provide generation of the microdata HTML markup. If you need to create HTML like the following one:

<div itemscope>
 <p>My name is
  <span itemprop="name">Elizabeth</span>.</p>
</div>

you will need to handle it yourself.

Note: nowadays microdata markup is considered to be outdated. It is recommened to use JSON Linked Data instead, which is supported by this extension.

RSS

This package does not support RSS feed generation or related meta data composition. Please consider usage one of the following packages for it:

Comments
  • Can't install on Laravel 5.7

    Can't install on Laravel 5.7

    Keep getting this error, this only happens with this package and 2 others... Any ideas?

    Problem 1 - Installation request for artesaos/seotools ^0.12.0 -> satisfiable by artesaos/seotools[v0.12.0]. - Conclusion: remove laravel/framework v5.7.0 - Conclusion: don't install laravel/framework v5.7.0 - artesaos/seotools v0.12.0 requires illuminate/support 5.0.* || 5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.* -> satisfiable by laravel/framework[5.1.x-dev, 5.2.x-dev, 5.3.x-dev, 5.4.x-dev, 5.5.x-dev, 5.6.x-dev], illuminate/support[5.0.x-dev, 5.1.x-dev, 5.2.x-dev, 5.3.x-dev, 5.4.x-dev, 5.5.x-dev, 5.6.x-dev, v5.0.0, v5.0.22, v5.0.25, v5.0.26, v5.0.28, v5.0.33, v5.0.4, v5.1.1, v5.1.13, v5.1.16, v5.1.2, v5.1.20, v5.1.22, v5.1.25, v5.1.28, v5.1.30, v5.1.31, v5.1.41, v5.1.6, v5.1.8, v5.2.0, v5.2.19, v5.2.21, v5.2.24, v5.2.25, v5.2.26, v5.2.27, v5.2.28, v5.2.31, v5.2.32, v5.2.37, v5.2.43, v5.2.45, v5.2.6, v5.2.7, v5.3.0, v5.3.16, v5.3.23, v5.3.4, v5.4.0, v5.4.13, v5.4.17, v5.4.19, v5.4.27, v5.4.36, v5.4.9, v5.5.0, v5.5.16, v5.5.17, v5.5.2, v5.5.28, v5.5.33, v5.5.34, v5.5.35, v5.5.36, v5.5.37, v5.5.39, v5.5.40, v5.5.41, v5.5.43, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.25, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9]. - Can only install one of: laravel/framework[5.5.x-dev, v5.7.0]. - Can only install one of: laravel/framework[5.6.x-dev, v5.7.0].

    opened by captenmasin 12
  • JSON-LD and schema.org [enhancement]

    JSON-LD and schema.org [enhancement]

    Google is currently using schema.org with JSON-LD format. Its quite similar to OpenGraph, so maybe you could add support for it as well.

    https://developers.google.com/search/docs/guides/intro-structured-data https://json-ld.org/playground/ http://schema.org/docs/full.html

    help wanted medium priority proposal 
    opened by hubertnnn 9
  • JsonLdMulti - Remove requirement for 2 items

    JsonLdMulti - Remove requirement for 2 items

    JsonLdMulti does not output anything on default; this is inconsistent with the use of JsonLd. The impact is high because this makes JsonLdMulti not be usable as default replacement for JsonLd.

    This pull request removes the check for minimum 2 items.

    | Q | A | ------------- | --- | Is bugfix? | ✔️ | New feature? | ❌ | Breaks BC? | ❌ | Tests pass? | ✔️ | Fixed issues | #275

    bug 
    opened by J-Brk 8
  • Please Add Laravel 7 Support

    Please Add Laravel 7 Support

    What steps will reproduce the problem?

    Attempting to update project to Laravel 7

    What is the expected result?

    Update

    What do you get instead?

    • artesaos/seotools v0.16.0 requires illuminate/support 5.8.*|^6.0 -> satisfiable by laravel/framework[v6.10.0], illuminate/support[5.8.x-dev, 6.x-dev, v5.8.0, v5.8.11, v5.8.12, v5.8.14, v5.8.15, v5.8.17, v5.8.18, v5.8.19, v5.8.2, v5.8.20, v5.8.22, v5.8.24, v5.8.27, v5.8.28, v5.8.29, v5.8.3, v5.8.30, v5.8.31, v5.8.32, v5.8.33, v5.8.34, v5.8.35, v5.8.36, v5.8.4, v5.8.8, v5.8.9, v6.0.0, v6.0.1, v6.0.2, v6.0.3, v6.0.4, v6.1.0, v6.10.0, v6.11.0, v6.12.0, v6.13.0, v6.13.1, v6.14.0, v6.15.0, v6.15.1, v6.16.0, v6.17.0, v6.17.1, v6.18.0, v6.2.0, v6.3.0, v6.4.1, v6.5.0, v6.5.1, v6.5.2, v6.6.0, v6.6.1, v6.6.2, v6.7.0, v6.8.0].
    opened by peterplant88 7
  • generating the JsonLD array having multiple JsonLD objects

    generating the JsonLD array having multiple JsonLD objects

    generating the JsonLD array having multiple JsonLD objects as given,

    [ 
       { 
          "@context":"http://schema.org",
          "@type":"Product",
          "aggregateRating":{ 
             "@type":"AggregateRating",
             "ratingValue":3.7,
             "reviewCount":8034
          },
          "brand":{ 
             "@type":"Thing",
             "name":"Anand Sarees"
          },
          "image":"http://rukmini1.flixcart.com/image/128/128/k51cpe80/sari/m/z/t/free-printed-fashion-georgette-saree-multicolor-khodiyar-original-imaempjvcuqbhe2g.jpeg?q=70",
          "name":"Anand Sarees Striped Daily Wear Poly Georgette Saree"
       },
       { 
          "@context":"http://schema.org",
          "@type":"BreadcrumbList",
          "itemListElement":[ 
             { 
                "@type":"ListItem",
                "item":{ 
                   "@id":"https://www.flipkart.com/womens-clothing/pr?sid=2oq,c1r&marketplace=FLIPKART&otracker=product_breadCrumbs_Women%27s+Clothing",
                   "name":"Women's Clothing"
                },
                "position":3
             },
             { 
                "@type":"ListItem",
                "item":{ 
                   "@id":"https://www.flipkart.com/womens-clothing/ethnic-wear/pr?sid=2oq,c1r,3pj&marketplace=FLIPKART&otracker=product_breadCrumbs_Ethnic+Wear",
                   "name":"Ethnic Wear"
                },
                "position":4
             },
             { 
                "@type":"ListItem",
                "item":{ 
                   "@id":"https://www.flipkart.com/sarees/anand-sarees~brand/pr?sid=2oq,c1r,3pj,7od&marketplace=FLIPKART&otracker=product_breadCrumbs_Anand+Sarees+Sarees",
                   "name":"Anand Sarees Sarees"
                },
                "position":6
             }
          ]
       }
    ]
    

    I want to generate the JsonLD array but didn't find the method to do it. Is it possible with this package or I need to modify? Let me know if there is no such method, I'll create a pull request for that.

    help wanted question 
    opened by vkiranmaniya 7
  • UTF-8 characteres not showing correctly

    UTF-8 characteres not showing correctly

    I am using this SEOMeta::setDescription("les entreprises dans leur quête de performance, grâce à ses solutions d’amélioration de la qualité de vie et de fidélisation des salariés");

    but I get this in page source code: <meta name="description" content="les entreprises dans leur qu&ecirc;te de performance, gr&acirc;ce &agrave; ses solutions d&rsquo;am&eacute;lioration de la qualit&eacute; de vie et de fid&eacute;lisation des salari&eacute;s">

    help wanted medium priority awaiting feedback proposal 
    opened by siempay 7
  • article tags (array) generated as og:tag instead article:tag

    article tags (array) generated as og:tag instead article:tag

    hi, i just try this seo tools and i got this issue when i trying to generate article tag

    this is in my controller:

    OpenGraph::setArticle([
                    'published_time' => $par->post_time,
                    'author' => $par->author->user_fullname,
                    'section' => $category,
                    'tag' => $tags
                ]);
    

    when the $tags is string, it generated as: <meta property="article:tag" content="tag" />

    but when it's an array, it generated as: <meta property="og:tag" content="tag" />

    help wanted Hacktoberfest 
    opened by zafranf 7
  • Default Values

    Default Values

    What steps will reproduce the problem?

    Install the plugin

    What is the expected result?

    Empty defaults (Or even pulled from Laravel config)

    What do you get instead?

    Some weird defaults that do the opposite of helping SEO.

    
    <title>It's Over 9000!</title>
    --
      | <meta name="description" content="For those who helped create the Genki Dama">
      | <meta property="og:title" content="Over 9000 Thousand!" />
      | <meta property="og:description" content="For those who helped create the Genki Dama" />
    

    Why does the plugin do this? I shouldn't be required to publish configurations just to tweak values away from non-standard defaults.

    opened by iBotPeaches 6
  • Is this dead? [question]

    Is this dead? [question]

    Hello guys, I just implemented this in my code but why there are no any new releases for so long? I am pretty interested in json-ld implementation to be added into release at least. It there a future for this package? Thx guys for answer

    opened by tonoslav 6
  • Accents issue

    Accents issue

    I have a problem with accent it's not displayed correctly.

    Example:

    This is before setDescription: público

    This is after I setDescription: p&uacute ;blico -> the space is because this editor set correctly the accent

    The correct is the first line: público

    How I can fix this?

    opened by maganius 6
  • Prevent self-closing tag syntax

    Prevent self-closing tag syntax

    | Q | A | ------------- | --- | Is bugfix? | ❌ | New feature? | ✔️ | Breaks BC? | ❌ | Tests pass? | ✔️ | Fixed issues | -

    The w3c validator recently produces warnings, if you use the self-closing tag syntax.

    feature 
    opened by stefket 5
  • Dropping PhpSpec development dependency

    Dropping PhpSpec development dependency

    Problem

    The development dependencies require "phpspec/phpspec": "~5.1.1 || ^6.0". This version is not compatible with newer PHP versions; PHP 7.4 and above.

    PhpSpec seems to be barely used and can be found in two places:

    The last commit regarding those 2 files where in 2016.

    Proposed solution

    Dropping PhpSpec or alternatively upgrading it to a newer version.

    -- Package Version v0.22.0 / PHP version 8.1.2

    awaiting feedback proposal 
    opened by J-Brk 0
  • Add support to macro

    Add support to macro

    Support macro feature, so that we can use some of the code in multiple places.

    This is an exemple of use case: Macro file:

    SEO::macro('detail', function ($product) {
        SEO::jsonLd()->addValue('@graph', [
         '@type' => 'Product',
                    '@id' => request()->url() . '#product',
                    'name' => ucfirst($product->meta->name),
                    'url' => request()->url(),
                    'description' => ucfirst($product->meta->name)
                    //....
        ]);
    });
    
    

    And in controller we can use this: SEO::detail($product);

    | Q | A | ------------- | --- | Is bugfix? | ❌ | New feature? | ✔️ | Breaks BC? | ❌ | Tests pass? | ✔️ | Fixed issues | comma-separated list of tickets # fixed by the PR, if any

    opened by omarherri 4
  • OpenGraph::addProperty on array omits

    OpenGraph::addProperty on array omits "og" in property name

    What steps will reproduce the problem?

    OpenGraph::addProperty('locale:alternate', ['en_GB', 'el_EL']);

    What is the expected result?

    <meta property="og:locale:alternate" content="en_GB" />
    <meta property="og:locale:alternate" content="el_EL" />
    

    What do you get instead?

    <meta property=":locale:alternate" content="en_GB" />
    <meta property=":locale:alternate" content="el_EL" />
    

    Additional info

    | Q | A | ------------------------- | --- | This Package Version | 0.20.0 | Laravel Framework Version | 8.34.0 | PHP version | 8.03 | Operating system | MacOs

    bug high priority 
    opened by schrink 2
  • Is this package support macro ?

    Is this package support macro ?

    can you please tell me if this package support macro feature, so that i can use some of the code in multiple places.

    this is an exemple of use case:

    Macro file:

    SEO::macro('detail', function ($product) {
        SEO::jsonLd()->addValue('@graph', [
         '@type' => 'Product',
                    '@id' => request()->url() . '#product',
                    'name' => ucfirst($product->meta->name),
                    'url' => request()->url(),
                    'description' => ucfirst($product->meta->name)
                    //....
        ]);
    });
    

    And in my controller i can use this: SEO::detail($product);

    feature proposal Hacktoberfest 
    opened by omarherri 1
  • Remove

    Remove "illuminate/config" dependency

    At the present state this package uses Illuminate\Config\Repository for the Artesaos\SEOTools\SEOMeta implementation. This produces an extra dependency to the "illuminate/config" package.

    SEOMeta is the only class using Illuminate\Config\Repository - all other SEO tools operate plain arrays.

    It is better to refactor Artesaos\SEOTools\SEOMeta removing usage of Illuminate\Config\Repository. It will make this class more consistent, easy for standalone usage and eliminates extra composer dependency.

    | Q | A | ------------------------- | --- | This Package Version | 0.15.0 | Laravel Framework Version | 5.8.31 | PHP version | 7.2 | Operating system | *

    opened by klimov-paul 0
Releases(v1.0.0)
  • v1.0.0(Sep 28, 2022)

    This major version does not break anything, just prevent any possible problem from #287 changes.

    What's Changed

    • Prevent self-closing tag syntax by @stefket in https://github.com/artesaos/seotools/pull/287

    New Contributors

    • @stefket made their first contribution in https://github.com/artesaos/seotools/pull/287

    Full Changelog: https://github.com/artesaos/seotools/compare/v0.23.0...v1.0.0

    Source code(tar.gz)
    Source code(zip)
  • v0.23.0(Aug 29, 2022)

    Thanks to @J-Brk and @elegasoft

    What's Changed

    • GitHub workflow integration by @J-Brk in https://github.com/artesaos/seotools/pull/285
    • Bump composer dependencies for php 8.0+ by @elegasoft in https://github.com/artesaos/seotools/pull/280

    New Contributors

    • @elegasoft made their first contribution in https://github.com/artesaos/seotools/pull/280

    Full Changelog: https://github.com/artesaos/seotools/compare/v0.22.1...v0.23.0

    Source code(tar.gz)
    Source code(zip)
  • v0.22.1(Jul 19, 2022)

  • v0.22.0(Feb 12, 2022)

  • v0.21.0(Feb 6, 2022)

  • v0.20.2(Sep 29, 2021)

  • v0.20.1(May 3, 2021)

    • #249 #247 : XSS in canonical tag
    • #244 #245 : isEmpty Url check
    • #248 update method hints in JsonLd facades

    Thanks to @J-Brk , @rajakhoury and @brentmullen

    Source code(tar.gz)
    Source code(zip)
  • v0.20.0(Dec 27, 2020)

    • Fix JSON-LD returns escaped URL's #236 by @xf039
    • Fix OpenGraph generate tags from array #74 #233 #217 bt @Ali-Shaikh
    • Use PHP 8 on travis tests
    Source code(tar.gz)
    Source code(zip)
  • v0.19.1(Oct 14, 2020)

  • v0.19.0(Sep 14, 2020)

  • v0.18.0(Jun 19, 2020)

    Fix and improves

    • #203 Fix cyrillic symbols by @vlados
    • #216 add JsonLd alias in composer.json @joke2k
    • #192 Fix testcases @slavarazum
    • #197 Add possibility to generate few JsonLd Group @yepzy
    Source code(tar.gz)
    Source code(zip)
  • v0.17.2(Apr 2, 2020)

  • v0.17.1(Mar 11, 2020)

    Fix and improviments

    #193 Fix #183: Ability to override Open Graph Url, if default url set to false #206 Add Norton safeweb to webmaster tags list #212 Remove usage of helper function array_forget

    Source code(tar.gz)
    Source code(zip)
  • v0.17.0(Mar 11, 2020)

  • v0.16.0(Sep 5, 2019)

    | PR | Autor | Fix | |-----|------|-----| | #181 Support Laravel 6.0, | @madeITBelgium | #178 | | #178 Add class="notranslate" to meta tag | @peterangelov | #139 | | #176 Add 'missing features' docs | @klimov-paul | #17, #18, #75 | | #175 Add facades PHPDoc | @klimov-paul | | | #174 Add class PHPDoc | @klimov-paul | | | #173 Add logo to readme | @klimov-paul | | | #166 JsonLd default URL generation | @klimov-paul | #165 | | #162 Change licence file to markdown | @klimov-paul | |

    Source code(tar.gz)
    Source code(zip)
  • v0.15.0(Aug 12, 2019)

    • #148 #145 Fix hard coded set url method while config is null @duongtdvn
    • #151 #133 add ability to put defaults.title before page title / support RTL title @kurumbus
    • #141 Add json-ld notation generator @EdwinHoksberg @klimov-paul
    • #155 #156 Use Illuminate\Contracts\Support\DeferrableProvider @klimov-paul
    • #122 #159 UTF-8 encoding for the meta tags @klimov-paul
    • #160 Fix PHPDoc @klimov-paul
    • #132 #106 #67 Add basic support for setting meta robots @peterangelov
    Source code(tar.gz)
    Source code(zip)
  • v0.14.0(Mar 8, 2019)

  • v0.13.0(Mar 7, 2019)

    Thanks for the PRs. #126 Update readme for Twitter setImage @sbtsrbayer #127 Update the keys for place to match og documentation @swilla #132 Add basic support for setting meta robots @peterangelov

    Source code(tar.gz)
    Source code(zip)
  • v0.12.0(Apr 19, 2018)

  • v0.11.1(Sep 25, 2017)

  • v0.10.0(Oct 27, 2016)

  • v0.9.2(Mar 25, 2016)

    Changelog

    General Fixes typo Minor bugs and improved code

    • Metags (thanks @biptaste )
      • setCanonical
      • getCanonical
      • setPrev
      • getPrev
      • setNext
      • getNext
      • addAlternateLanguage
      • addAlternateLanguages
      • getAlternateLanguages

    Default canonical value (thanks for @mauri870 ) Buugfix #58 (thanks for @edbizarro )

    Source code(tar.gz)
    Source code(zip)
  • v0.8.2(Jan 7, 2016)

    Changelog

    • seotools
      • getTitle
    • metatags (thanks for @georgeboot )
      • setTitle $appendDefault
      • setDefaultTitle
    • opengraph (thanks for @mcnub)
      • article
      • profile
      • book
      • music
      • video
      • audio

    TODO

    • tests in opengraph
    Source code(tar.gz)
    Source code(zip)
  • v0.7.4(Apr 29, 2015)

  • 0.4.1(Mar 10, 2015)

Owner
Artesãos
Artesãos
Laravel Seo package for Content writer/admin/web master who do not know programming but want to edit/update SEO tags from dashboard

Laravel Seo Tools Laravel is becoming more and more popular and lots of web application are developing. In most of the web application there need some

Tuhin Bepari 130 Dec 23, 2022
SEO Tools for Laravel

SEOTools - SEO Tools for Laravel and Lumen SEOTools is a package for Laravel 5.8+ and Lumen that provides helpers for some common SEO techniques. Curr

Artesãos 2.7k Dec 31, 2022
This repo is for the Laracon 2021 talk "Manage SEO with Laravel and Nova"

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Kristin 7 Dec 9, 2022
Easily setup SEO in your laravel project with lara-head :heart: @code4mk

installation composer require code4mk/lara-head usage meta ~ inside controller use Khead; class Test { public function home() { Khead::setMeta

null 173 Dec 23, 2022
Seo Manager Package for Laravel ( with Localization )

Seo Manager Package for Laravel ( with Localization ) lionix/seo-manager package will provide you an interface from where you can manage all your page

Lionix 205 Dec 23, 2022
A package to handle the SEO in any Laravel application, big or small.

Never worry about SEO in Laravel again! Currently there aren't that many SEO-packages for Laravel and the available ones are quite complex to set up a

Ralph J. Smit 267 Jan 2, 2023
A convenient helper for using the laravel-seo package with Filament Admin and Forms

Combine the power of Laravel SEO and Filament PHP. This package is a convenient helper for using the laravel-seo package with Filament Admin and Forms

Ralph J. Smit 39 Dec 21, 2022
Laravel package for manage your URL redirects in database or other sources to get better SEO results

Laravel 8 and 9 package to manage URL redirections inside your Laravel application using different data sources. It allows a better SEO support for your Laravel site.

Siro Díaz Palazón 51 Sep 21, 2022
This is an open source demo of administration panel for polymorphic relationship and SEO content

Laravel SEO admin This application demonstrates usage of polymorphic relationships described at (http://maxoffsky.com/code-blog/using-polymorphic-rela

Maksim Surguy 127 Oct 11, 2022
Laravel lsp - Developer tools for easier Laravel development

Laravel lsp The Laravel/Blade lsp provides: Blade: Diagnostics on missing components + action to create it. Autocomplete for components and their argu

Harings Rob 32 Dec 21, 2022
Laravel Inspector, debugging and profiling tools for Web Artisans

Laravel Inspector At a Glance Installation Configuration Usage Messages Timers Redirects Dump and die Exceptions VIEW/AJAX/API requests, how it works

null 240 Dec 8, 2022
Tools for creating Laravel packages

Tools for creating Laravel packages This package contains a PackageServiceProvider that you can use in your packages to easily register config files,

Spatie 526 Dec 29, 2022
Builder - A handful of tools for Rapid Laravel Development

Grafite Builder Grafite has archived this project and no longer supports or develops the code. We recommend using only as a source of ideas for your o

Grafite Inc 997 Dec 22, 2022
A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro

Laravel Myanmar Tools A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro. Installation composer require pyaesoneaung/larave

Pyae Sone Aung 22 Dec 20, 2022
Laravel is accessible, powerful, and provides tools required for large, robust applications.

Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be trul

Web & Mobile | eCommerce | Full-Stack Developer 4 Nov 24, 2022
A collection of tools for rapidly building beautiful TALL stack interfaces, designed for humans.

Filament is a collection of tools for rapidly building beautiful TALL stack interfaces, designed for humans. Packages Admin Panel • Documentation • De

Filament 5.4k Jan 4, 2023
Geo-related tools PHP 7.3+ library built atop Geocoder and React libraries

Geotools Geotools is a PHP geo-related library, built atop Geocoder and React libraries. Features Batch geocode & reverse geocoding request(s) in seri

The League of Extraordinary Packages 1.3k Dec 27, 2022
Add a general-purpose tools page to your Filament project. 🛠

Add a general-purpose tools page to your Filament project. Installation You can install the package via Composer: composer require ryangjchandler/fila

Ryan Chandler 24 Dec 6, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel Spark.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Jan 2, 2023