Code Monkey home page Code Monkey logo

laravelmetatags's Introduction

meta-tags

The most powerful and extendable tools for managing SEO Meta Tags in your Laravel project

Laravel SEO Meta Tags offers a sophisticated solution for Laravel applications, allowing developers to seamlessly manage header meta tags, CSS, JavaScript, and other relevant tags. Its primary objective is to simplify the process of managing search engine optimization (SEO) tags within your application.

Moreover, its versatile API makes it compatible with frameworks like Inertiajs, VueJS and other JavaScript frameworks.

For any questions or further assistance, please join our official telegram group

Contributing

We enthusiastically invite you to contribute to the package! Whether you've uncovered a bug, have innovative feature suggestions, or wish to contribute in any other capacity, we warmly welcome your participation. Simply open an issue or submit a pull request on our GitHub repository to get started.

Remember, every great developer was once a beginner. Contributing to open source projects is a step in your journey to becoming a better developer. So, don't hesitate to jump in and start contributing!

We appreciate any contributions to help make the package better!

Support me on Patreon

Build Status Latest Stable Version Total Downloads License

Supercharge Your Development with Buggregator

Pair it with our package for a more robust development environment. For more informatino visit buggregator.dev

Features

  • Meta Management: Effortlessly set titles, charset, pagination links, and more.
  • Styles & Scripts: Organize and place styles and scripts anywhere in your HTML.
  • Custom Tags: Make your own tags to suit specific needs.
  • Rich Media Integration: Supports both Open Graph & Twitter Cards.
  • Analytics Ready: Comes with Google Analytics and Yandex Metrika tracking code support, including a code builder for the latter.
  • Site Verification: Supports webmaster tools site verifier tags.
  • Package System: Group tags, styles, and scripts into named packages for easy inclusion anywhere.
  • Robust Documentation: Clear instructions and guidelines for a seamless setup.
  • Thoroughly Tested: Built to ensure reliability and stability.

Requirements

  • Laravel version: 9.x to 10.x
  • PHP version: 8.0 or higher

Installation and Configuration

  1. Install the package: Use the following command to install the Meta Tags package in your awesome application.
composer require butschster/meta-tags
  1. Register the Service Provider: After installing the package, you must register its service provider.

You can do it using the following artisan command:

php artisan meta-tags:install

This command will activate the App\Providers\MetaTagsServiceProvider and publish the configuration at config/meta_tags.php. Within this configuration file, you can set default titles, keywords, descriptions, and other meta tags which will be automatically inserted into your HTML.

  1. Verification: Ensure that App\Providers\MetaTagsServiceProvider has been added to the providers array in your config/app.php configuration file. If it hasn't, you'll need to add it manually. Remember, if your application isn't using the App namespace, update the provider class name accordingly.

And that's all! Your Laravel project is now equipped to handle SEO meta tags with ease.

Usage

Controller

You can use either Facade \Butschster\Head\Facades\Meta or \Butschster\Head\Contracts\MetaTags\MetaInterface in your controller

use Butschster\Head\MetaTags\MetaInterface;

class HomeController extends Controller
{
    public function __contruct(
        protected MetaInterface $meta
    ) {
    }
    
    public function index()
    {
        $news = News::paginate();
        
        // Prepend title part to the default title
        $this->meta
        
            // Will render "Home page - Default Title"
           ->prependTitle('Home page')
           
           // Will include next, prev, canonical links
           ->setPaginationLinks($news)
           
           // Will change default favicon
           ->setFavicon('/favicon-index.ico')
    }
}

// Or you can use the facade

use Butschster\Head\Facades\Meta;

class HomeController extends Controller 
{
    public function index()
    {
        $news = News::paginate();
        
        Meta::prependTitle('Home page')
            ->setPaginationLinks($news)
            ->setFavicon('favicon-index.ico');
    }
}

View

To integrate meta tags into your HTML, simply insert {!! Meta::toHtml() !!} wherever required.

Note You have two options to insert meta tags: {!! Meta::toHtml() !!} or the Blade directive @meta_tags.

Here's an example of how you can use it in your view:

<!DOCTYPE html>
<html lang="en">
<head>
    {!! Meta::toHtml() !!}
</head>
...
</html>

Placements

The package provides flexibility to insert meta tags beyond the header. You can define specific placements in your templates.

  • To place meta tags in the footer, use: Meta::footer()->toHtml()
  • For custom placements, use: Meta::placement('placement_name')->toHtml()
  • Alternatively, the Blade directive can also be used: @meta_tags('placement_name')
<body>
...
{!! Meta::placement('middle_of_the_page')->toHtml() !!}
...
{!! Meta::footer()->toHtml() !!}
</body>

Packages

To avoid code repetition and improve code organization, you can group tags, assets, etc., into named packages. This allows for streamlined inclusion of sets of meta tags or assets where needed.

To create a new package:

  • Navigate to the Service provider.
  • Add your package within \App\Providers\MetaTagsServiceProvider.

To define packages, you can use the PackageManager::create method:

namespace App\Providers;

use Butschster\Head\Facades\PackageManager;
use Butschster\Head\Packages\Package;
use Illuminate\Support\ServiceProvider;

class MetaTagsServiceProvider extends ServiceProvider 
{
    ...
    protected function packages()
    {
       PackageManager::create('jquery', function(Package $package) {
          $package->addScript(
             'jquery.js', 
             'https://code.jquery.com/jquery-3.3.1.min.js', 
             ['defer']
          );
       });
       
       PackageManager::create('calendar', function(Package $package) {
          $package->requires('jquery');
          $package->addScript(
             'fullcalendar.js', 
             'https://cdn.jsdelivr.net/npm/@fullcalendar/[email protected]/main.min.js', 
             ['defer']
          )->addScript(
             'fullcalendar.locales.js', 
             'https://cdn.jsdelivr.net/npm/@fullcalendar/[email protected]/locales-all.min.js', 
             ['defer']
          )->addStyle(
             'fullcalendar.css', 
             'https://cdn.jsdelivr.net/npm/@fullcalendar/[email protected]/main.min.css'
          );
       });
    }

    ...
}

Using Packages in Controllers

When specific packages are required within a controller, you can include them by referencing the package name:

use Butschster\Head\Facades\Meta;

class EventsController extends Controller {

    public function show(Event $event)
    {
        // Will include all tags from calendar package
        Meta::includePackages(['calendar', ...]);
    }
}

Setting Global Packages

For packages that should be included on every page, you can define them in the config/meta_tags.php:

...
'packages' => [
    'jquery', 'calendar', ...
],
...

And there you have it! With these steps, handling and organizing meta tags and assets becomes a breeze.

Note All methods available in the Meta class can also be utilized alongside these package functions.

API

Meta

\Butschster\Head\MetaTags\Meta

  • This class implements Illuminate\Contracts\Support\Htmlable interface

Methods

Set the main part of meta title

Meta::setTitle('Laravel');
// <title>Laravel</title>

// You can specify max length. (By default it gets from config.)
Meta::setTitle('Laravel', 4);
// <title>Lara...</title>

Prepend title part to main title

Meta::setTitle('Laravel')
    ->prependTitle('Home page');
// <title>Home page - Laravel</title>

Set the title separator

By default it gets from config

Meta::setTitleSeparator('->')
    ->setTitle('Laravel')
    ->prependTitle('Home page');
// <title>Home page -> Laravel</title>

Set the description

Meta::setDescription('Awesome page');
// <meta name="description" content="Awesome page">

// You can specify max length. (By default it gets from config.)
Meta::setDescription('Awesome page', 7);
// <meta name="description" content="Awesome...">

Set the keywords

Meta::setKeywords('Awesome keywords');
// <meta name="keywords" content="Awesome keywords">


Meta::setKeywords(['Awesome keyword', 'keyword2']);
// <meta name="keywords" content="Awesome keyword, keyword2">

// You can specify max length. (By default it gets from config.)
Meta::setKeywords(['keyword', 'keyword2'], 10);
// <meta name="keywords" content="keyword, key...">

Set the robots

Meta::setRobots('nofollow,noindex');
// <meta name="robots" content="nofollow,noindex">

Set the content type

Meta::setContentType('text/html');
// <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

Meta::setContentType('text/html', 'ISO-8859-1');
// <meta http-equiv="Content-Type" content="text/html; ISO-8859-1">

Set the viewport

Meta::setViewport('width=device-width, initial-scale=1');
// <meta name="viewport" content="width=device-width, initial-scale=1">

Add webmaster tags You can add multiple tags

use Butschster\Head\MetaTags\Entities\Webmaster;

// Supported services [google, yandex, pinterest, alexa, bing]
Meta::addWebmaster(Webmaster::GOOGLE, 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="google-site-verification" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('yandex', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="yandex-verification" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('bing', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="msvalidate.01" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('alexa', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="alexaVerifyID" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster(Webmaster::PINTEREST, 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="p:domain_verify" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Set the prev href

Meta::setPrevHref('http://site.com/prev');
// <link rel="prev" href="http://site.com/prev" />

Set the next href

Meta::setNextHref('http://site.com/next');
// <link rel="next" href="http://site.com/next" />

Set the canonical link

Meta::setCanonical('http://site.com');
// <link rel="canonical" href="http://site.com" />

Set canonical link, prev and next from paginator object

$news = \App\News::paginate();

Meta::setPaginationLinks($news);

// <link rel="prev" href="http://site.com/prev" />
// <link rel="next" href="http://site.com/next" />
// <link rel="canonical" href="http://site.com" />

Add a hreflang link

Meta::setHrefLang('en', http://site.com/en');
Meta::setHrefLang('ru', http://site.com/ru');

// <link rel="alternate" hreflang="en" href="http://site.com/en" />
// <link rel="alternate" hreflang="ru" href="http://site.com/ru" />

Set the character encoding for the HTML document

Meta::setCharset();
// <meta charset="utf-8">

Meta::setCharset('ISO-8859-1');
// <meta charset="ISO-8859-1">

Set the favicon

Meta::setFavicon('http://site.com/favicon.ico');
// <link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />

Meta::setFavicon('http://site.com/favicon.png');
// <link rel="icon" type="image/png" href="http://site.com/favicon.png" />

Meta::setFavicon('http://site.com/favicon.gif');
// <link rel="icon" type="image/gif" href="http://site.com/favicon.gif" />

Meta::setFavicon('http://site.com/favicon.svg');
// <link rel="icon" type="image/svg+xml" href="http://site.com/favicon.svg" />

//You can set additional attributes
Meta::setFavicon('http://site.com/favicon.svg', ['sizes' => '16x16', 'type' => 'custom_type']);
// <link rel="icon" type="custom_type" href="http://site.com/favicon.svg" sizes="16x16" />

Add a custom link tag

Meta::addLink('apple-touch-icon-precomposed', [
    'href' => 'http://site.com',
    'id' => 'id:213'
]);
// <link rel="apple-touch-icon-precomposed" href="http://site.com" id="id:213" />

Add a link to a css file

Meta::addStyle('style.css', 'http://site.com/style.css');
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />


// You can override or add attributes
Meta::addStyle('style.css', 'http://site.com/style.css', [
    'media' => 'custom', 'defer', 'async'
]);

// <link media="custom" type="text/css" rel="stylesheet" href="http://site.com/style.css" defer async />

Add a link to a script file

Meta::addScript('script.js', 'http://site.com/script.js');
// <script src="http://site.com/script.js"></script>

// You can override or add attributes
Meta::addScript('script.js', 'http://site.com/script.js', ['async', 'defer', 'id' => 'hj2b3424iu2-dfsfsd']);
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

// You can specify placement. By default, for scripts it's footer
Meta::addScript('script.js', 'http://site.com/script.js', [], 'custom_placement');
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

Register a custom tag Our package has a lot of ways of extending. One of them is creating new tags. You are able to create a new class and share it with friends or with the laravel community. You can also create a new pull request if you think that your awesome tag is really useful.

class FacebookPixelTag implements \Butschster\Head\Contracts\MetaTags\Entities\TagInterface {

    private $pixel_id;

    public function __construct(string $id)
    {
        $this->pixel_id = $id
    }
   
    public function getPlacement(): string
    {
        return 'footer'
    }

    public function toArray()
    {
        return [
            'type' => 'facebook_pixel_tag',
            'pixel_id' => $this->pixel_id
        ];
    }
    
    public function toHtml()
    {
        return '<script type="text/javascript">...</script>'
    }
}

Meta::addTag('facebook.pixel', new FacebookPixelTag('42b3h23-34234'));
// <script type="text/javascript">...</script>

Register tags from TagsCollection

$tags = new \Butschster\Head\MetaTags\TagsCollection([
    ...
]);
Meta::registerTags($tags);

// You can specify the placement 
Meta::registerTags($tags, 'footer');

Get a tag by name

Meta::getTag('author');

Remove a tag by name

Meta::removeTag('author');

Add a meta tag

Meta::addMeta('author', [
    'content' => 'butschster',
]);
// <meta name="author" content="butschster">

Add the CSRF-token tag

Meta::addCsrfToken();
// <meta name="csrf-token" content="....">

Remove all tags

Meta::reset();

Include required packages

Meta::includePackages('jquery', 'vuejs');
Meta::includePackages(['jquery', 'vuejs']);

Will load registered packages with names jquery and vuejs and append tags from there to Meta

Register a new package and register all tags from this package

Meta::setTitle('Current title');

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('New title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);

Replace package with the same name When you replace package with a new one, old tags will be removed

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

$newPackage = new \Butschster\Head\Packages\Package('custom_package');
$newPackage->setTitle('New title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);
Meta::replacePackage($newPackage);

Remove package by name

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);
Meta::removePackage('custom_package');

Get package by name

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);

$package = Meta::getPackage('custom_package');

Using meta interfaces

A package has different interfaces which help you set meta tags from your objects

Seo tags

namespace App;
use Butschster\Head\Contracts\MetaTags\SeoMetaTagsInterface;
use Butschster\Head\Contracts\MetaTags\RobotsTagsInterface;

class Page extends Model implements SeoMetaTagsInterface, RobotsTagsInterface {

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function getKeywords()
    {
        return $this->keywords;
    }

    public function getRobots(): ?string
    {
        return 'noindex, nofollow';
    }
}

// Controller
use Butschster\Head\Facades\Meta;

class PageController extends Controller {

    public function show(\App\Page $page)
    {
        Meta::setMetaFrom($page);
    }
}

Meta extending

Meta object contains Macroable trait and you can extend it!

For example

//Service Provider
Meta::macro('registerSeoMetaTagsForPage', function (\App\Page $page) {
    $this
        ->prependTitle($page->title)
        ->setKeywords($page->meta_keywords)
        ->setDescription($page->meta_description);
 
});

// Controller
use Butschster\Head\Facades\Meta;

class PageController extends Controller {

    public function show(\App\Page $page)
    {
        Meta::registerSeoMetaTagsForPage($page);
    }
}

A little bit infirmation about macroable trait https://unnikked.ga/understanding-the-laravel-macroable-trait-dab051f09172

Meta tags placements

By default, tags place to head placement. You can specify your own placement and use their all available methods.

Meta::placement('twitter.meta')
    ->addMeta('twitter:card', [
        'content' => 'summary_large_image',
    ])
    ->includePackages('twitter')

// There is the method for footer placement
Meta::footer()->...
    
// View
<body>
    ...
    @meta_tags('twitter.meta')
    ...
    
    @meta_tags('footer')
</body>

Package

A package object has the same methods as Meta object. You can use it for extending and creating custom tags sets.

\Butschster\Head\Packages\Package

  • This class extend Butschster\Head\MetaTags\Meta class
  • This class implements Illuminate\Contracts\Support\Htmlable interface

Create a new package and register it in PackageManager

$package = new \Butschster\Head\Packages\Package('jquery');
PackageManager::register($package);

// or
PackageManager::create('jquery', function($package) {
    ...
});

Get the name of the package

$package = new \Butschster\Head\Packages\Package('jquery');

$package->getName(); // jquery

Add a link to a css file

$package = new \Butschster\Head\Packages\Package('jquery');

$package->addStyle('style.css', 'http://site.com/style.css');
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />


// You can change or add attributes
$package->addStyle('style.css', 'http://site.com/style.css', [
    'media' => 'custom', 'defer', 'async'
]);

// <link media="custom" type="text/css" rel="stylesheet" href="http://site.com/style.css" defer async />

Add a link to a script file

$package = new \Butschster\Head\Packages\Package('jquery');

$package->addScript('script.js', 'http://site.com/script.js');
// <script src="http://site.com/script.js"></script>

// You can change or add attributes
$package->addScript('script.js', 'http://site.com/script.js', ['async', 'defer', 'id' => 'hj2b3424iu2-dfsfsd']);
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

// You can placement. By default it's footer
$package->addScript('script.js', 'http://site.com/script.js', [], 'custom_placement');
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

Meta::includePackages('jquery')->placement('custom_placement')->toHtml();

Available packages


OpenGraphPackage

Butschster\Head\Packages\Entities\OpenGraphPackage

You can use this package for managing OpenGraph meta tags

$og = new Butschster\Head\Packages\Entities\OpenGraphPackage('some_name');

$og->setType('website')
   ->setSiteName('My awesome site')
   ->setTitle('Post title');
   
// You can render itself

$og->toHtml();
// <meta name="og:type" content="website">
// <meta name="og:site_name" content="My awesome site">
// <meta name="og:title" content="Post title">

// Or just register this package in Meta class and it will be rendered automatically
Meta::registerPackage($og);

setType Set the type of your object, e.g., "video.movie".

$og->setType('website');
// <meta name="og:type" content="website">

setTitle Set the title of your object as it should appear within the graph, e.g., "The Rock".

$og->setTitle('Post title');
// <meta name="og:title" content="Post title">

setDescription Set the description

$og->setDescription('View the album on Flickr.');
// <meta name="og:description" content="View the album on Flickr.">

setSiteName Set the site name

$og->setSiteName('My awesome site');
// <meta name="og:site_name" content="My awesome site">

setUrl Set the canonical URL of your object that will be used as its permanent ID in the graph.

$og->setUrl('https://site.com');
// <meta name="og:url" content="https://site.com">

setLocale Set the locale these tags are marked up in. Of the format language_TERRITORY

$og->setLocale('en_US');
// <meta name="og:locale" content="en_US">

addAlternateLocale

$og->addAlternateLocale('en_US', 'ru_RU');
// <meta name="og:locale:alternate" content="en_US">
// <meta name="og:locale:alternate" content="ru_RU">

addImage Add an image URL which should represent your object within the graph.

$og->addImage('http://site.com');
// <meta name="og:image" content="http://site.com">

// You can pass properties
$og->addImage('http://site.com', [
    'secure_url' => 'https://site.com',
    'type' => 'image/png'
]);

// <meta name="og:image" content="http://site.com">
// <meta name="og:image:secure_url" content="https://site.com">
// <meta name="og:image:type" content="image/png">

addVideo Add an image URL which should represent your object within the graph.

$og->addVideo('http://site.com');
// <meta name="og:video" content="http://site.com">

// You can pass properties
$og->addVideo('http://site.com', [
    'secure_url' => 'https://site.com',
    'type' => 'application/x-shockwave-flash'
]);

// <meta name="og:video" content="http://site.com">
// <meta name="og:video:secure_url" content="https://site.com">
// <meta name="og:video:type" content="application/x-shockwave-flash">

TwitterCardPackage

Butschster\Head\Packages\Entities\TwitterCardPackage

You can use this package for managing Twitter card meta tags

$card = new Butschster\Head\Packages\Entities\TwitterCardPackage('some_name');

$card->setType('summary')
   ->setSite('@username')
   ->setTitle('Post title');
   
// You can render itself

$card->toHtml();
// <meta name="twitter:card" content="summary">
// <meta name="twitter:site" content="@username">
// <meta name="twitter:title" content="Post title">

// Or just register this package in Meta class and it will be rendered automatically
Meta::registerPackage($card);

setType Set the type of the card: summary, summary_large_image, player, app

$card->setType('summary');
// <meta name="twitter:card" content="summary">

setSite Set the @username for the website used in the card footer.

$card->setSite('@username');
// <meta name="twitter:site" content="@username">

setCreator Set the @username for the content creator / author.

$card->setCreator('@username');
// <meta name="twitter:creator" content="@username">

setTitle Set the title

$card->setTitle('Post title');
// <meta name="twitter:title" content="Post title">

setDescription Set the description

$card->setDescription('View the album on Flickr.');
// <meta name="twitter:title" content="View the album on Flickr.">

setImage Set an image for cards that are of type summary or summary_large_image

$card->setImage('https://site.com');
// <meta name="twitter:image" content="https://site.com">

setVideo Set a video to cards that are of type player

$card->setVideo('https://site.com/video.mp4', ['width' => 1920, 'height' => 1280]);
// <meta name="twitter:player" content="https://site.com/video.mp4">
// <meta name="twitter:player:width" content="1920">
// <meta name="twitter:player:height" content="1280">

addMeta Set a custom meta tag

$card->addMeta('image:alt', 'Picture of Pavel Buchnev');
// <meta name="twitter:image:alt" content="Picture of Pavel Buchnev">

PackageManager API

Package manager provide a store for your packages or presets. You can get them by name.

Create a new package

PackageManager::create('jquery', function($package) {
    ...
});

Register a new package

$package = new \Butschster\Head\Packages\Package('jquery');

PackageManager::register($package);

Get all registered packages

PackageManager::getPackages(): array;

Get registered package by name

PackageManager::create('jquery', function($package) {
    ...
});

PackageManager::getPackage('jquery'); 
// Will return the registered pacakge or null;

Dependencies

A package can have dependencies.

PackageManager::create('jquery', function($package) {
    $package->addScript('jquery.js', 'http://site.com/jquery.min.js');
});

PackageManager::create('bootstrap4', function($package) {
    $package->requires('jquery');
    $package->addScript('bootstrap4.js', 'http://site.com/bootstrap4.min.js');
    $package->addStyle('bootstrap4.css', 'http://site.com/bootstrap4.min.css');
});

Meta::includePackages('bootstrap4'); 
// Will load jquery package also
// Head
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/bootstrap4.min.css" />

// Footer
// <script src="http://site.com/jquery.min.js"></script>
// <script src="http://site.com/bootstrap4.min.js"></script>

Helper classes

Tag


\Butschster\Head\MetaTags\Entities\Tag

Create a new tag

$tag = new \Butschster\Head\MetaTags\Entities\Tag('meta', [
    'name' => 'author',
    'content' => 'butschster'
]);
// or
$tag = \Butschster\Head\MetaTags\Entities\Tag::meta([
    'name' => 'author',
    'content' => 'butschster'
]);
$tag->toHtml();
// <meta name="author" content="butschster">

// Closed tag
$tag = new \Butschster\Head\MetaTags\Entities\Tag('link', [
    'rel' => 'favicon',
    'href' => 'http://site.com'
], true);
// or
$tag = \Butschster\Head\MetaTags\Entities\Tag::link([
    'rel' => 'favicon',
    'href' => 'http://site.com'
]);

$tag->toHtml();
// <link rel="favicon" href="http://site.com" />

// Tag with anonymous function
$tag = new \Butschster\Head\MetaTags\Entities\Tag('meta', [
    'name' => 'csrf-token',
    'content' => function () {
        return Session::token();
    }
]);

$tag->toHtml();
// <meta name="csrf-token" content="8760b1d530d60d2cba6fe81cb12d67c0">

Set the placement

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->setPlacement('footer');

Get the placement

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->getPlacement() // Will return specified placement;

Set visibility condition

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->visibleWhen(function () {
    return Request::ip() === '127.0.0.1';
});

Title


\Butschster\Head\MetaTags\Entities\Title

This class is responsible for title generation

Set the default part of the title

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');

$title->toHtml(); // <title>Laravel</title>

Prepend a new part of title

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');
$title->prepend('Index page');

$title->toHtml(); // <title>Index page | Laravel</title>

Change default title parts separator

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');
$title->prepend('Index page');
$title->setSeparator('-');

$title->toHtml(); // <title>Index page - Laravel</title>

Specify max length (default length is 255)

$title = new \Butschster\Head\MetaTags\Entities\Title('Lorem Ipsum is simply dummy text of the printing and typesetting');

$title->setMaxLength(20);

$title->toHtml(); // <title>Lorem Ipsum is simpl...</title>

Description


\Butschster\Head\MetaTags\Entities\Description

Script


\Butschster\Head\MetaTags\Entities\Script

This class is responsible for script links generation

use Butschster\Head\MetaTags\Entities\Script;

$script = new Script('jquery.js', 'http://site.com/script.js', ['defer', 'async']);

$script->toHtml(); 
// <script src="http://site.com/script.js" defer async></script>

Meta::addTag($script);

Style


\Butschster\Head\MetaTags\Entities\Style

This class is responsible for css links generation

use Butschster\Head\MetaTags\Entities\Style;

$style = new Style('style.css', 'http://site.com/style.css');

$style->toHtml(); 
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />

Meta::addTag($style);

Favicon


\Butschster\Head\MetaTags\Entities\Favicon

This class is responsible for favicon link generation

Comment


\Butschster\Head\MetaTags\Entities\Comment

This class is a wrapper for tags, that allows to add comments to your tags

use Butschster\Head\MetaTags\Entities\Comment;
use Butschster\Head\MetaTags\Entities\Favicon;

$favicon = new Favicon('http://site.com/favicon.ico');
$comment = new Comment($favicon, 'Favicon');

Meta::addTag('favicon', $comment);

// Will render
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />
<!-- /Favicon -->

Conditional comment


\Butschster\Head\MetaTags\Entities\ConditionalComment

This class is a wrapper for tags, that allows to add conditional comments to your tags

use Butschster\Head\MetaTags\Entities\ConditionalComment;
use Butschster\Head\MetaTags\Entities\Favicon;

$favicon = new Favicon('http://site.com/favicon.ico');
$comment = new ConditionalComment($favicon, 'IE 6');

Meta::addTag('favicon', $comment);
<!--[if IE 6]>
<link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />
<![endif]-->

Google Analytics


Has header placement!

use Butschster\Head\MetaTags\Entities\GoogleAnalytics;
$script = new GoogleAnalytics('UA-12345678-1');

Meta::addTag('google.analytics', $script);

Will return

<script>
    (function (i, s, o, g, r, a, m) {
        i['GoogleAnalyticsObject'] = r;
        i[r] = i[r] || function () {
            (i[r].q = i[r].q || []).push(arguments)
        }, i[r].l = 1 * new Date();
        a = s.createElement(o),
                m = s.getElementsByTagName(o)[0];
        a.async = 1;
        a.src = g;
        m.parentNode.insertBefore(a, m)
    })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
    ga('create', 'UA-12345678-1', 'auto');
    ga('send', 'pageview');
</script>

Google TagManager


Has header placement!

use Butschster\Head\MetaTags\Entities\GoogleTagManager;
$script = new GoogleTagManager('UA-12345678-1');

Meta::addTag('google.tagmanager', $script);

Will return

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-12345678-1"></script>
<script>
    window.dataLayer = window.dataLayer || [];

    function gtag() {
        dataLayer.push(arguments);
    }

    gtag('js', new Date());

    gtag('config', 'UA-12345678-1');
</script>

Yandex Metrika


Has footer placement!

use \Butschster\Head\MetaTags\Entities\YandexMetrika;
$script = new YandexMetrika('20925319');

Meta::addTag('yandex.metrika', $script);

Will return

<script type="text/javascript">
    (function (m, e, t, r, i, k, a) {
        m[i] = m[i] || function () {
            (m[i].a = m[i].a || []).push(arguments)
        };
        m[i].l = 1 * new Date();
        k = e.createElement(t), a = e.getElementsByTagName(t)[0], k.async = 1, k.src = r, a.parentNode.insertBefore(k, a)
    })
    (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");

    ym(20925319, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true, webvisor: true});
</script>
<noscript>
    <div><img src="https://mc.yandex.ru/watch/20925319" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>

Change clickmap setting

$script = new YandexMetrika('20925319');

$script->clickmap(bool);

Change webvisor setting

$script = new YandexMetrika('20925319');

$script->webvisor(bool);

Change trackLinks setting

$script = new YandexMetrika('20925319');

$script->trackLinks(bool);

Change accurateTrackBounce setting

$script = new YandexMetrika('20925319');

$script->accurateTrackBounce(bool);

Change trackHash setting

$script = new YandexMetrika('20925319');

$script->trackHash(bool);

Change eCommerce setting

$script = new YandexMetrika('20925319');

$script->eCommerce(string $containerName);

Use alternate CDN

$script = new YandexMetrika('20925319');

$script->useCDN();

Disable noscript tag

$script = new YandexMetrika('20925319');

$script->disableNoScript();

Javascript variables


use \Butschster\Head\MetaTags\Entities\JavascriptVariables;

$variables = new JavascriptVariables([
    'string' => 'Hello world',
    'number' => 4815162342,
    'bool' => true,
    'nullable' => null
]);

// you can put new variable
$variables->put('array', ['jquery', 'vuejs']);

Meta::addTag('variables', $variables);

Will return

<script>
    window.array = ["jquery", "vuejs"];
    window.string = 'Hello world';
    window.number = 4815162342;
    window.bool = true;
    window.nullable = null;
</script>

You can change namespace

use \Butschster\Head\MetaTags\Entities\JavascriptVariables;

$variables = new JavascriptVariables([
    'string' => 'Hello world',
    'number' => 4815162342,
], 'custom');

Will return

<script>
    window.custom = window.custom || {};
    custom.string = 'Hello world';
    custom.number = 4815162342;
</script>

Use cases

Multiple favicons

You can use your own package for that.

At first create your package in the MetaTagsServiceProvider App\Providers\MetaTagsServiceProvider

namespace App\Providers;

use Butschster\Head\MetaTags\Entities\Favicon;
use Butschster\Head\MetaTags\Entities\ConditionalComment;
use Butschster\Head\Facades\PackageManager;
use Butschster\Head\Packages\Package;

class MetaTagsServiceProvider extends ServiceProvider {

    ...
    
    protected function packages()
    {
        PackageManager::create('favicons', function(Package $package) {
            $sizes = ['16x16', '32x32', '64x64'];
    
            foreach ($sizes as $size) {
                $package->addTag(
                    'favicon.'.$size, 
                    new Favicon('http://site.com/favicon-'.$size.'.png', [
                        'sizes' => $size
                    ])
                );
            }
    
            $package->addTag('favicon.ie', new ConditionalComment(
                new Favicon('http://site.com/favicon-ie.png'), 'IE gt 6'
            ));
        });
    }
    
    ...
}

And then append this package into packages section in config/meta_tags.php:

...
'packages' => [
    'favicons'
],
...

And the every page you will see in the head seaction something like that:

<head>
    ...
    <title>...</title>
    <link rel="icon" type="image/png" href="http://site.com/favicon-16x16.png" sizes="16x16"/>
    <link rel="icon" type="image/png" href="http://site.com/favicon-32x32.png" sizes="32x32"/>
    <link rel="icon" type="image/png" href="http://site.com/favicon-64x64.png" sizes="64x64"/>
    <!--[if IE gt 6]>
    <link rel="icon" type="image/png" href="http://site.com/favicon-ie.png" />
    <![endif]-->
    ...
</head>

Extending

If you want to extend Meta class you can do it in the App\Providers\MetaTagsServiceProvider. Just override registerMeta method.

namespace App\Providers;

use Butschster\Head\MetaTags\Meta;
use Butschster\Head\Contracts\MetaTags\MetaInterface;
use Butschster\Head\Contracts\Packages\ManagerInterface;

class MetaTagsServiceProvider {

    ...

    protected function registerMeta(): void
    {
        $this->app->singleton(MetaInterface::class, function () {
            $meta = new Meta(
                $this->app[ManagerInterface::class],
                $this->app['config']
            );
    
    
            // It just an imagination, you can automatically 
            // add favicon if it exists
            if (file_exists(public_path('favicon.ico'))) {
                $meta->setFavicon('/favicon.ico');
            }
    
            $meta->includePackages('fonts', 'assets');
            
            // This method gets default values from config and creates tags
            // If you don't want to use default values just remove it.
            $meta->initialize();
    
            return $meta;
        });
    }

    ...
}

Using with inertiajs or vue-meta

You can easily convert Meta object to array ant the use values in your Js project

$meta = Meta::setTitle('Laravel')
    ->setDescription('Awesome page')
    ->setKeywords('php, laravel, ...');

dd($meta->toArray());

[
    'head' => [
        [
            'tag' => 'title',
            'content' => 'Laravel',
        ],
        [
            'name' => 'description',
            'content' => 'Awesome page',
            'type' => 'tag',
            'tag' => 'meta',
        ],
        [
            'name' => 'keywords',
            'content' => 'php, laravel, ...',
            'type' => 'tag',
            'tag' => 'meta',
        ],
    ]
]

Example for inertiaJs

use Inertia\Inertia;
use Butschster\Head\MetaTags\MetaInterface;
use Butschster\Head\Hydrator\VueMetaHydrator;

class EventsController extends Controller
{
    protected $meta;
 
    public function __contruct(MetaInterface $meta)
    {
        $this->meta = $meta;
    }
    
    public function show(Event $event, VueMetaHydrator $hydrator)
    {
        $this->meta->setTitle('Laravel')
            ->setDescription('Awesome page')
            ->setKeywords('php, laravel, ...');
    
        return Inertia::render('Event/Show', [
            'event' => $event->only('id', 'title', 'start_date', 'description'),
            
            // this.$page.props.meta...
            'meta' => $hydrator->hydrate($this->meta)
        ]);
    }
}

laravelmetatags's People

Contributors

atiksoftware avatar butschster avatar henryavila avatar hladenkyi avatar imsus avatar joserick avatar jwcobb avatar laravel-shift avatar loranger avatar mohamedsabil83 avatar nguyentranchung avatar uintaam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravelmetatags's Issues

Facade example shows static method usage; however the functions are not actually static

Describe the bug
Facade examples show static method usage however the function definitions are not static functions.

To Reproduce
Use a facade implementation with ::setTitle or any other method and you will see it is not compatible with actual function definition.

Expected behavior
There should be no errors when using static methods with the Facade.

Screenshots
image

image

Ampersand in query string gets incorrectly escaped

Describe the bug
This seems to be same issue as #5

To Reproduce

Write the following code

Meta::setHrefLang('zh-Hans', 'https://example.com/?foo=bar&lang=zh-hans');

Expected behavior

It outputs

<link rel="alternate" hreflang="zh-Hans" href="https://example.com/?foo=bar&amp;lang=zh-hans">

When it should output

<link rel="alternate" hreflang="zh-Hans" href="https://example.com/?foo=bar&lang=zh-hans">

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Currently I'm replacing all ampersands in my URLs with ESCAPED_AMPERSAND and then other way around after outputting the meta tags. It's not the best way to fix the issue but it works.

Cannot install on Laravel 7

@butschster

Describe the bug
Trait 'Illuminate\Console\DetectsApplicationNamespace' not found

# composer require butschster/meta-tags
Using version ^1.6 for butschster/meta-tags
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing butschster/meta-tags (v1.6.5): Loading from cache
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi

   Symfony\Component\ErrorHandler\Error\FatalError

  Trait 'Illuminate\Console\DetectsApplicationNamespace' not found

  at C:\Work\www\projects\dummy\vendor\butschster\meta-tags\src\Console\InstallCommand.php:9
     5| use Illuminate\Console\Command;
     6| use Illuminate\Console\DetectsApplicationNamespace;
     7| use Illuminate\Support\Str;
     8|
  >  9| class InstallCommand extends Command
    10| {
    11|     use DetectsApplicationNamespace;
    12|
    13|     /**

To Reproduce
Steps to reproduce the behavior:

  1. Create a fresh Laravel 7 project
  2. Install this package: composer require butschster/meta-tags

Expected behavior
Package installed without errors

Desktop (please complete the following information):

  • OS: Windows 10 / Ubuntu 18.04
  • PHP 7.4.3 (no opcache) / nginx 1.17.8
  • Browser: Any

How to generate custom meta tag?

Hi
I need to create custom meta tags like this one <meta itemprop="arc:custom-name" content="meta content"> but even I pass an empty sting to name, the result is <meta name="" itemprop="arc:custom-name" content="meta content">.

Is there any way to achieve the pretended output?

Thanks in advance.

Cheers
rjs

access tag value

I need to access meta tag value but when I get a tag and then trying to get value property is private, is there any way to do that?

My current code is:
Meta::getTag("title")->title

Support for property tag

Is there any way to include "property" tag, besides or instead of "name"?

For example, many OG meta are documented to be written with property tag:
https://ogp.me/#structured

How can I write something like this ?

<meta property="og:title" content="The Rock" />
<meta property="og:type" content="video.movie" />
<meta property="og:url" content="https://www.imdb.com/title/tt0117500/" />
<meta property="og:image" content="https://ia.media-imdb.com/images/rock.jpg" />

Thank you

with PHP 8 I got error "require int, null given"

src/MetaTags/Entities/Title.php
with PHP 8 I got error "require int, null given"

fix it with adding "|null"
line 39: public function __construct(string $title = null, int|null $maxLength = self::DEFAULT_LENGTH)

Missing PHPDocblock on the Facade

  • "laravel/framework": "^8.0",
  • "butschster/meta-tags": "^1.13",
  • "barryvdh/laravel-ide-helper": "^2.8",

I'm using laravel-ide-helper in PHPStorm and found the Facade class is missing a small PHPDocblock which prevents code completion.

Here is the small missing DocBlock:

/**
 * Class Meta
 * @package Butschster\Head\Facades
 * @mixin MetaInterface
 */
class Meta extends Facade {
}

OpenGraph wrong tag attributename

In the OpenGraphPackage you are using the same tag generator like other meta-tags, but this is not working for OpenGraph:
Generated, wrong tag: <meta name="og:type" content="website">
Correct tag would be: <meta property="og:type" content="website">

See: https://developers.facebook.com/docs/sharing/webmasters

My quick "bugfix" local, is to extend vendor/butschster/meta-tags/src/Packages/Entities/Concerns/ManageMeta.php with:

public function addOgMeta(string $key, string $content)
{
$key = $this->prefix.$key;
$this->tags->put($key, Tag::meta([
'property' => $key,
'content' => $content,
]));
return $this;
}

And replace $this->addMeta with $this->addOgMeta in vendor/butschster/meta-tags/src/Packages/Entities/OpenGraphPackage.php

Add Yandex metrika script builder

It would be cool to use builder for building yandex metrika script.

Something like this:

$tag = new YandexMetrika(20925319);
$tag->webvisor(false)->useCDN()->clickmap(false);

Bug with csrf token

При подключение пакета через конструктор контроллера, не генерируется csrf token

Вставка description с кавычками

Когда вставляю текст с кавычками, тогда эти кавычки не экранируются.

<meta property="og:description" content="Some "text" with quotes">

phpunit tests fail when @meta_tags is in a view

I'm using this package for a while which works great. Now I am writing tests for my application but they fail when @meta_tags is present in the view.

Any idea how to resolve this?

I already tried to to remove all meta data in my custom code. This does not resolve the issue.

The exception

(1/1) InvalidArgumentException
Action Facade\Ignition\Http\Controllers\ShareReportController not defined.

The test

    public function testBasicTest()
    {
//        $this->withExceptionHandling();
        $response = $this->get('/');
        $response->dump();

        $response->assertStatus(200);
    }

Php unit result

F                                                                  2 / 2 (100%)

Time: 278 ms, Memory: 28.00 MB

There was 1 failure:

1) Tests\Feature\ExampleTest::testBasicTest
Expected status code 200 but received 500.
Failed asserting that false is true.

/Users/simonvanthuijl/PhpstormProjects/gv/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:166
/Users/simonvanthuijl/PhpstormProjects/gv/tests/Feature/ExampleTest.php:21

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
Simons-MacBook-Pro:gv simonvanthuijl$ 

html output from the dump function
Screen Shot 2019-10-22 at 00 20 29

Cannot call abstract method

Hello,

If I write this code, as the doc says, I get this message returned by phpStorm. My page doesn't bug but the editor doesn't seem to like it.

use Butschster\Head\Facades\Meta;

Meta::setTitle('Dashboard')
            ->setDescription('Dashboard');

Cannot call abstract method 'MetaInterface::setTitle'

Is there anything I can do?
Thank you

Laravel 10 : Installing/updating any version from 3.0.1 throws a fatal error

When installing/updating the package in a Laravel 10 project, a fatal error occurs:

PHP Fatal error: A void function must not return a value in /var/www/laravel10/vendor/butschster/meta-tags/src/Console/InstallCommand.php on line 38

To Reproduce

  1. Install the latest Laravel 10 version
  2. composer require butschster/meta-tags
  3. Error

This commit is the cause of the issue: 43086d3

Note: Forcing the version to 3.0.0 fixes the issue.

Changes via package not reflected in `Meta::toHtml()`

Describe the bug
I've registered 2 packages, "twitter" and "facebook" (og) via the MetaTagsServiceProvider (in boot method). Eg: when using $package = Meta::getPackage('facebook') and then modifying some og tags, these changes are not reflected in the html output (using Meta::toHtml() in the base view). I have to call Meta::replacePackage($package) explicitly in the controller to make the html render the updated tags.

Is this intended behaviour? For me the replacePackage call feels a bit counter intuitive and redundant because I already registered the package to be included by default (via config).

To Reproduce

  1. Register a default package (OpenGraph)
  2. Set some default values
  3. In a Controller, get the package, change eg the title
  4. check HTML as it will not reflect the updated title

Expected behavior
it should reflect changes immediately (without replace package)

Screenshots
/

Desktop (please complete the following information):

  • OS: MacOS
  • Browser FF
  • Version /

Not replacing default values

Describe the bug
I've set default values to config file based on documentation but they never get updated on my routes.

To Reproduce

Expected behavior

Getting my dynamic data meta

Screenshots

012

Desktop (please complete the following information):

  • OS: Win
  • Browser Opera
  • Version 10

Smartphone (please complete the following information):

  • Device: -
  • OS: -
  • Browser -
  • Version -

Additional context

my controller

use Butschster\Head\Facades\Meta;

///

$post = Post::where('slug', $slug)->where('online', true)->with(['user', 'user.posts', 'likes', 'categories'])->first();
if($post){
  views($post)->record();
  Meta::setTitle('Laravel')
   ->prependTitle($post->name)
   ->setKeywords(['a', 'b', 'c'])
   ->setDescription($post->body);
}

Method `addScript()` not working

Describe the bug

There's no displayed error with this one, it's just the script tag that doesn't show up in the browser's source code.

// MetaTagsServiceProvider.php

protected function packages()
{
    // *NOTE THE COMMENTS BELLOW...
    PackageManager::create('app', function (Package $package) {
        $package->addScript('app.js', asset('js/app.js'), ['defer']);
    });
}

protected function registerMeta(): void
{
  $this->app->singleton(MetaInterface::class, function () {
      $meta = new Meta(
          $this->app[ManagerInterface::class],
          $this->app['config']
      );

      $meta->initialize();

      $meta->addLink('app.css', [
          'href' => asset('css/app.css'),
          'rel'  => 'stylesheet'
      ]);

      $meta->addLink('bootstrap-icons', [
          'rel'  => 'stylesheet',
          'href' => 'https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css'
      ]);

      // FIRST I TRIED THIS AND IT'S NOT WORKING...
      $meta->addScript('app.js', asset('js/app.js'), ['defer']);
      // THEN I TRIED IN THIS WAY BUT DOESN'T WORK EITHER*
      $meta->includePackages(['app']);

      return $meta;
  });
}
<!doctype html>
<html lang="en" class="h-100">
<head>
    <!-- META -->
    <title>My App</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="597dIm5sGMaTTI90tbPTs9l2QYFsJEOULSQi4Vwx">
<link href="http://myapp.test/css/app.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">    <!-- END META -->
</head>

Expected behavior
I expect to see <script src="http://myapp.test/js/app.js" defer></script> in the <head> tag on every page.

Multiple CSS

Describe the bug
When using addStyle multiple times, only the last one is inserted into the page via toHtml. I can't see to find a way of adding multiple stylesheets using the API

To Reproduce
Meta::addStyle('style.css', 'http://site.com/style1.css');
Meta::addStyle('style.css', 'http://site.com/style2.css');

Only style2.css is inserted into the page.

<link media="all" type="text/css" rel="stylesheet" href="http://site.com/style2.css">

Expected behavior
I would expect both to be inserted.

<link media="all" type="text/css" rel="stylesheet" href="http://site.com/style1.css">
<link media="all" type="text/css" rel="stylesheet" href="http://site.com/style2.css">

Additional context
Also, the name parameter is ignored, and doesn't seem to be used, so there's no need to pass style.css

    /**
     * @param string $name
     * @param string $src
     * @param array $attributes
     */
    public function __construct(string $name, string $src, array $attributes = [])
    {
        $this->name = $name;
        $this->src = $src;

        parent::__construct('link', $attributes, false);
    }

    /**
     * @return array
     */
    protected function getAttributes(): array
    {
        return array_merge([
            'media' => 'all',
            'type' => 'text/css',
            'rel' => 'stylesheet',
            'href' => $this->src,
        ], parent::getAttributes());
    }

I would guess this might also be the case for addScript?

Get Tag's attributes as a property

Is your feature request related to a problem? Please describe.
Get the current value of a tags property. Eg, I wanted to get the current title that was set, as a string. But I had to do something like Meta::getTitle()->toArray()['content'] to get the string value.

Describe the solution you'd like
Can we leverage PHP's magic methods on the base Tag to get the value of a tag's attribute as a property? Like Meta::getTitle()->content (I know title is a special implementation, so maybe not the best example though)

Describe alternatives you've considered
See above

How I can use multiple "Apple Touch Icon" with addLink() method?

Trying to use addLink() method to add multiple apple-touch-icon but only one is added to HTML because the package use an array_merge. How I can to do this?

Meta::addLink('apple-touch-icon', [
    'href' => asset('apple-icon-57x57.png'),
    'sizes' => '57x57',
])
->addLink('apple-touch-icon', [
    'href' => asset('apple-icon-60x60.png'),
    'sizes' => '60x60',
])
...

Full HTML tags:

<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192"  href="/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">

Some Name

What is the name that I have to put here? I don't understand this part, thanks

$og = new Butschster\Head\Packages\Entities\OpenGraphPackage('some_name');

AddProviderToBootstrapFile Error

I am using Laravel 10. When I update the package from 3.0.0 to 3.0.2, I got an error:

Whoops\Run::handleError("A void function must not return a value", "butschster\meta-tags\src\Console\InstallCommand.php")

if (file_exists($this->getLaravel()->bootstrapPath('providers.php'))) {
// @phpstan-ignore-next-line
return ServiceProvider::addProviderToBootstrapFile("{$namespace}\Providers\MetaTagsServiceProvider"); <-- Error here
}

Overwriting default OpenGraph values

image

I have added default values in the service provider to show as default on all pages for OpenGraph, however, I need certain pages to pass their own values.

image

The above should have used the post values, but instead I still get the default values from the service provider.

How do I override values on a case by case basis?

Условия отображения элементов

Стоит предусмотреть возможность скрывать или отображать информацию при наступлении определенных условий, например версия браузера, IP, тип устройства, клиент и т.д.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.