# Meta Tags Plugin

**URL:** <https://forum.getkirby.com/t/meta-tags-plugin/6802>\
**Category:** Plugins\
**Created:** [March 1, 2017, 4:59am UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802 "2017-03-01T04:59:04Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [March 1, 2017, 4:59am UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/1 "2017-03-01T04:59:04Z")

</div>

HTML meta tags generator for Kirby. Supports Open Graph and Twitter Cards out of the box.

> **[pedroborges/kirby-meta-tags](https://github.com/pedroborges/kirby-meta-tags)**
>
> kirby-meta-tags - HTML meta tags generator for Kirby. Supports Open Graph and Twitter Cards out of the box.

```
$ kirby plugin:install pedroborges/kirby-meta-tags

```

## Basic Usage

After installing the Meta Tags plugin, you will need to add one line to the `head` element on your template, or `header.php` snippet:

```diff
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
+ <?php echo $page->metaTags() ?>

```

### Default

The plugin ships with some default meta tags enabled for your convenience:

```php
c::set('meta-tags.default', [
    'title' => site()->title(),
    'meta' => [
        'description' => site()->description()
    ],
    'link' => [
        'canonical' => page()->url()
    ],
    'og' => [
        'title' => page()->title(),
        'type' => 'website',
        'site_name' => site()->title(),
        'url' => page()->url()
    ]
]);

```

**The `meta-tags.default` option is applied to all pages on your Kirby site.** Of course you can and I encourage you to change these defaults. In order to do that, you just need to copy this example to your `site/config/config.php` and tweak it to fit your needs.

### Templates

Following the flexible spirit of Kirby, you also have the option to add template specific meta tags:

```php
c::set('meta-tags.templates', [
    'article' => [ // template name
        'og' => [ // tags group name
            'type' => 'article', // overrides the default
            'namespace:article' => function($page) {
                return [
                    'author' => $page->author(),
                    'published_time' => $page->date('%F'),
                    'modified_time' => $page->modified('%F'),
                    'tag' => ['tech', 'web']
                ];
            },
            'namespace:image' => function($page) {
                $image = $page->cover()->toFile();

                return [
                    'image' => $image->url(),
                    'width' => $image->width(),
                    'height' => $image->height(),
                    'type' => $image->mime()
                ];
            }
        ]
    ],
]);

```

When a template key matches the current page’s template name, it is merged and overrides any repeating properties defined on the `meta-tags.default` option so you don’t have to repeat yourself.

## Result HTML

```auto
<!-- merged default definition -->
<title>Pedro Borges</title>
<meta name="description" content="My personal website">
<meta property="og:title" content="My blog post title">
<meta property="og:site_name" content="Pedro Borges">
<meta property="og:url" content="https://pedroborg.es/blog/my-article">
<!-- template definition -->
<meta property="og:type" content="article">
<meta property="og:article:author" content="Pedro Borges">
<meta property="og:article:published_time" content="2017-02-28">
<meta property="og:article:modified_time" content="2017-03-01">
<meta property="og:article:tag" content="tech">
<meta property="og:article:tag" content="web">
<meta property="og:image" content="https://pedroborg.es/content/blog/my-article/cover.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:type" content="image/jpeg">
<link rel="canonical" href="https://pedroborg.es/blog/my-article">

```

There are a lot of more examples on the [repo](https://github.com/pedroborges/kirby-meta-tags).

---

<div class="post-metadata">

**Author:** ![kinkwilde](https://avatars.discourse-cdn.com/v4/letter/k/94ad74/32.png) [@kinkwilde](https://forum.getkirby.com/u/kinkwilde)\
**Post date:** [July 9, 2017, 3:42pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/2 "2017-07-09T15:42:46Z")

</div>

Can I create custom meta tags and links? If yes, how do I go about doing that? Could you provide an example. Something like a humans.txt or a google notranslate.

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [November 15, 2017, 3:08pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/3 "2017-11-15T15:08:02Z")

</div>

## Release v1.0.0

The previous version has been stable enough and no issue has been reported in 8 months 😃

I finally got time to make some improvements and update the documentation so it’s time to release [v1.0.0](https://github.com/pedroborges/kirby-meta-tags/tree/v1.0.0).

### Changed

- Options `meta-tags.default` and `meta-tags.templates` can now return a `closure` which receives `$page` and `$site` as arguments:

- Closures in other places now receive `$site` and second argument as well:

Besides offering a better workflow, these changes also help avoid an issue where `site()` can’t be called outside a closure from the config file in multi-language websites, as reported on the [Kirby repository](https://github.com/getkirby/kirby/issues/606).

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [November 15, 2017, 3:15pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/4 "2017-11-15T15:15:39Z")

</div>

> [@kinkwilde](#):
>
> Can I create custom meta tags and links? If yes, how do I go about doing that? Could you provide an example. Something like a humans.txt or a google notranslate.

Hi @kinkwilde, sorry for missing your question a few months ago. You may have found the answer already but I want to share an example from a project I’m working on because it may help others, as well.

```php
c::set('meta-tags.default', function(Page $page, Site $site) {
    $name = $site->name();
    $title = $page->isHomePage()
                ? $site->title().' / '.$name
                : $page->title().' / '.$name;
    $description = $page->isHomePage()
                ? $site->description()->html()
                : $page->description()->html();

    return [
        'title' => $title,
        'meta' => [
            'description' => $description,
            'application-name' => $name->html(),
            'apple-mobile-web-app-title' => $name->html(),
            'apple-mobile-web-app-status-bar-style' => '#6767ad',
        ],
        'link' => [
            'canonical' => $page->url(),
            'icon' => [
                ['href' => url('assets/images/icons/favicon-16.png'), 'sizes' => '16x16', 'type' =>'image/png'],
                ['href' => url('assets/images/icons/favicon-32.png'), 'sizes' => '32x32', 'type' =>'image/png'],
                ['href' => url('assets/images/icons/favicon-96.png'), 'sizes' => '96x96', 'type' =>'image/png']
            ],
            'apple-touch-icon' => [
                ['href' => url('assets/images/icons/apple-touch-icon-152.png'), 'sizes' => '152x152', 'type' =>'image/png'],
                ['href' => url('assets/images/icons/apple-touch-icon-167.png'), 'sizes' => '167x167', 'type' =>'image/png'],
                ['href' => url('assets/images/icons/apple-touch-icon-180.png'), 'sizes' => '180x180', 'type' =>'image/png'],
            ],
            'stylesheet' => [
                ['href' => url('assets/css/main.css')]
            ],
        ],
        'og' => [
            'site_name' => $name->html(),
            'url' => $page->url(),
            'type' => 'website',
            'title' => $page->isHomePage()
                ? $site->title()
                : $page->title(),
            'description' => $description,
            'image' => url('assets/images/cover.png'),
        ],
        'twitter' => [
            'site' => $site->twitter(),
            'card' => 'summary_large_image',
            'title' => $page->isHomePage()
                ? $site->title()
                : $page->title(),
            'description' => $description,
            'image' => url('assets/images/cover.png'),
        ]
    ];
});

```

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [July 7, 2018, 8:30pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/5 "2018-07-07T20:30:08Z")

</div>

# Release v1.1.0

This release adds support for JSON-LD schemas and a few other improvements, check it out on [Github](https://github.com/pedroborges/kirby-meta-tags/releases/tag/v1.1.0)!

### Added

- Support for JSON-LD schema:

- Support for rendering one tag or a specific group of tags:

### Fixed

- Tags with empty value being rendered with invalid markup.

---

<div class="post-metadata">

**Author:** ![luxlogica](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/luxlogica/32/437_2.png) [@luxlogica](https://forum.getkirby.com/u/luxlogica)\
**Post date:** [July 7, 2018, 11:58pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/6 "2018-07-07T23:58:54Z")

</div>

@pedroborges This is a pretty big update! Developers might not immediately realise that JSON-LD can be used to improve SEO rankings. To help educate them, you may want to **[point them to this page](https://developers.google.com/search/docs/guides/intro-structured-data)** in the Google Developers website.

Great work!

---

<div class="post-metadata">

**Author:** ![jimbobrjames](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimbobrjames/32/5802_2.png) [@jimbobrjames](https://forum.getkirby.com/u/jimbobrjames)\
**Post date:** [July 8, 2018, 7:44am UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/7 "2018-07-08T07:44:52Z")

</div>

@pedroborges This is fantastic! Well done. I can finally ditch my set of manually created set of schema snippets. This is the best Sunday morning ever. Does it support breadcrumb schema?

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [July 8, 2018, 8:05pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/8 "2018-07-08T20:05:34Z")

</div>

Thanks for the love guys!

@jimbobrjames you can use schema available at [schema.org](http://schema.org), just pass a multidimensional array to `json-ld` and the plugin will take care of the rest, like so:

```php
c::set('meta-tags.default', function ($page, $site) {
    $pages = $site->pages()->visible();
    $breadcrumb = [];

    foreach ($pages as $p) {
        $breadcrumb[] = [
            '@type' => 'ListItem',
            'position' => $p->num(),
            'item' => [
                '@id' => $p->url(),
                'name' => $p->title()->value(),
            ],
        ];
    }

    return [
        'title' => $page->title(),
        'meta' => [/* ... */],
        'link' => [/* ... */],
        'og' => [/* ... */],
        'twitter' => [/* ... */],
        'json-ld' => [
            'BreadcrumbList' => [
                'itemListElement' => $breadcrumb
            ]
        ]
    ];
});

```

The output when you call `$page->metaTags()` will be:

```auto
<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
        {
            "@type": "ListItem",
            "position": "1",
            "item": {
                "@id": "https://example.com",
                "name": "Homepage"
            }
        },
        {
            "@type": "ListItem",
            "position": "2",
            "item": {
                "@id": "https://tbm.test/about",
                "name": "About Us"
            }
        }
    ]
}
</script>

```

The first level `@context` and `@type` can be omitted and the plugin will include them for you, but you have to include the `@type` property for nested items.

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [July 8, 2018, 8:14pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/9 "2018-07-08T20:14:48Z")

</div>

Just found a small bug and pushed [v1.1.1](https://github.com/pedroborges/kirby-meta-tags/releases/tag/v1.1.1) to fix it. Update the plugin 😉

---

<div class="post-metadata">

**Author:** ![anon77445132](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@anon77445132](https://forum.getkirby.com/u/anon77445132)\
**Post date:** [August 31, 2018, 8:23pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/10 "2018-08-31T20:23:54Z")

</div>

@pedroborges:

Thanks for your Kirby Meta Tags plugin. To test it I have downloaded a new Kirby Starterkit 2.5.12, installed it, then added a new snippet `site/snippets/breadcrumb.php` with the source like [Kirby docs: Breadcrumb menu](https://getkirby.com/docs/cookbook/menus#breadcrumb), added the needed css for this and added `<?php snippet('breadcrumb') ?>` in the last line of the snippet `site/snippets/header.php`.

After this I installed your Kirby Meta Tags plugin, added a new line with `<?php echo $page->metaTags() ?>` in the “head” of the snippet `site/snippets/header.php` and added your [config](https://forum.getkirby.com/t/meta-tags-plugin/6802/8) to my `site/config/config.php`.

All works and I get NO error. Thanks.

But I have read [https://schema.org/BreadcrumbList](https://schema.org/BreadcrumbList), particularly the first two paragraphs.

If I look at the source code e.g. of my page “`projects/project-c`” I find a difference between the links of the Breadcrumb menu and the links in your BreadcrumbList. Also the numbering is not correct e.g. if the (blog) pages are sorted by date.

Therefore I do not consider your configuration to be correct with the meaning of [https://schema.org/BreadcrumbList](https://schema.org/BreadcrumbList) and suggest the following start of your [configuration](https://forum.getkirby.com/t/meta-tags-plugin/6802/8) :

```php
c::set('meta-tags.default', function ($page, $site) {
    $pages = $site->breadcrumb();
    $nn = 0;
    $breadcrumb = [];

    foreach ($pages as $p) {
        $breadcrumb[] = [
            '@type' => 'ListItem',
            'position' => ++$nn,
            'item' => [
                '@id' => $p->url(),
                'name' => $p->title()->value(),
            ],
        ];
    }

```

I am pleased about your feedback.

HeinerEF

---

<div class="post-metadata">

**Author:** ![portobien](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/portobien/32/7162_2.png) [@portobien](https://forum.getkirby.com/u/portobien)\
**Post date:** [January 25, 2020, 3:52pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/11 "2020-01-25T15:52:15Z")

</div>

I am wondering the following: is the plugin generating automatic some info? For example the meta-description. Or do you have to make a blueprint for the meta description. Is it even possible to influence some info from the plugin with a blueprint?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [January 25, 2020, 3:57pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/12 "2020-01-25T15:57:25Z")

</div>

@portobien The plugin uses default fields like the title or a `$site->description()` field, but you can adapt all that in the config settings, see the readme for details.

Depending on what fields you have set up, it might make sense to add dedicated fields for this purpose.

---

<div class="post-metadata">

**Author:** ![jimbobrjames](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimbobrjames/32/5802_2.png) [@jimbobrjames](https://forum.getkirby.com/u/jimbobrjames)\
**Post date:** [January 25, 2020, 4:01pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/13 "2020-01-25T16:01:53Z")

</div>

> [@portobien](#):
>
> For example the meta-description. Or do you have to make a blueprint for the meta description.

You could use my Chopper plugin, which will get a set amount of text from a field based on either a word or carachter count. This is useful for descriptions. I usually use it as a fallback for if the dedicated meta description field is empty.

> **[GitHub - HashandSalt/chopper: This plugin creates excerpts and keeps HTML tags.](https://github.com/HashandSalt/chopper)**
>
> This plugin creates excerpts and keeps HTML tags. Contribute to HashandSalt/chopper development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![portobien](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/portobien/32/7162_2.png) [@portobien](https://forum.getkirby.com/u/portobien)\
**Post date:** [January 25, 2020, 4:23pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/14 "2020-01-25T16:23:00Z")

</div>

Okay! But if you don’t change this then every page on the website has the same meta description? Am I right?

So could I change maybe the $site-\>description() to something like $page-\>metadescription() ?

---

<div class="post-metadata">

**Author:** ![portobien](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/portobien/32/7162_2.png) [@portobien](https://forum.getkirby.com/u/portobien)\
**Post date:** [January 25, 2020, 4:24pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/15 "2020-01-25T16:24:33Z")

</div>

Thanks sounds good! For Kirby 2 there where great (user input / visual) SEO plugins. I try to make one voor K3!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [January 25, 2020, 4:26pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/16 "2020-01-25T16:26:58Z")

</div>

Yes, looks like the default is to apply the same stuff to every page. All the page specific stuff is done via the options.

---

<div class="post-metadata">

**Author:** ![REH](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/reh/32/14669_2.png) [@REH](https://forum.getkirby.com/u/REH)\
**Post date:** [January 27, 2020, 2:00am UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/17 "2020-01-27T02:00:54Z")

</div>

> [@portobien](#):
>
> Thanks sounds good! For Kirby 2 there where great (user input / visual) SEO plugins. I try to make one voor K3!

I’ve developed one for Kirby 3 already, that I suggest you to check out and help improve, before developing your own. If it fits you, we might avoid having two plugins with the same purpose 😉

See my post in the other thread:  
[https://forum.getkirby.com/t/seo-for-kirby-3/13228/7?u=reh](https://forum.getkirby.com/t/seo-for-kirby-3/13228/7)

---

<div class="post-metadata">

**Author:** ![portobien](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/portobien/32/7162_2.png) [@portobien](https://forum.getkirby.com/u/portobien)\
**Post date:** [January 27, 2020, 3:07pm UTC](https://forum.getkirby.com/t/meta-tags-plugin/6802/18 "2020-01-27T15:07:49Z")

</div>

Thanks!
