zmark/seo-plugin

多语言 Winter CMS 网站的 SEO 和网站地图插件

安装: 51

依赖项: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 0

开放问题: 0

类型:winter-plugin

1.04 2022-10-04 13:50 UTC

This package is auto-updated.

Last update: 2024-09-04 17:47:40 UTC


README

多语言 SEO 插件

此插件允许为多语言网站创建 SEO 元内容。

它还会根据所需的 CMS 页面和其他内容生成多语言 sitemap.xml 文件。

CMS 页面、静态页面Rainlab 博客 文章和分类页面都支持 直接使用。自定义模型可以轻松扩展。网站地图功能来自 Rainlab 网站地图 插件。

它需要 Rainlab 翻译 插件才能运行。

使用多语言 SEO 组件

首先,您必须将 Seo 组件放置在主题布局的头部部分。

组件有两个可配置属性,称为 "prepend" 和 "append",如果您填写它们,内容将被添加到所有页面标题的开头或结尾。例如,如果页面标题是 "项目",append 属性是 "| 网站名称",则页面标题将显示为 "项目 | 网站名称"。

description = "Default layout"

[localePicker]
forceUrl = 1

...

[seo]
append = "| Site Name"
==
<!DOCTYPE html>
...

然后,您应该为您的主题中的每个页面创建一个 SEO 注册。在每个语言中填写标题、描述、(可选)关键词和(可选)图像。

最后,像这样在布局中显示元数据

<title>{{ this.page.meta_title }}</title>
<meta name="description" content="{{ this.page.meta_description }}" />
<meta name="keywords" content="{{ this.page.meta_keywords }}" />
<meta name="title" content="{{ this.page.meta_title }}" />

<meta property="og:title" content="{{ this.page.meta_title }}" />
<meta property="og:description" content="{{ this.page.meta_description }}" />
{% if this.page.seo_image %}
<meta property="og:image" content="{{ this.page.seo_image.getPath() }}" />
{% endif %}

对静态页面插件的支持

如果您使用 Rainlab.Pages 插件,您还可以为这些静态页面创建 SEO 数据。您需要将 SEO 组件添加到静态布局中。

对博客插件的支撑

博客插件的文章和分类页面自动支持。安装博客插件并创建文章和分类页面后,只需从下拉列表中选择类型 "博客文章" 或 "博客分类",然后选择一个页面并填写数据即可。

您还需要将 SeoModel 组件添加到文章或分类页面(无需设置 pageType 和 pageProperty 选项)

[seoModel]

对自定义模型的支持

您可以为您的模型创建 SEO 数据。

您的插件必须监听 Rainlab.Pages 使用来构建动态菜单的以下事件

  • pages.menuitem.listType 事件处理程序应返回可以附加 SEO 数据的对象类型的列表。
  • pages.menuitem.getTypeInfo 事件处理程序返回对象类型的所有项。

此监听器的一个示例(此代码为简化此插件目的而简化,Rainlab.Pages 菜单需要更多数据)

public function boot()
{
    Event::listen('pages.menuitem.listTypes', function() {
        return [
            'acme-post' => 'Post page',
        ];
    });

    Event::listen('pages.menuitem.getTypeInfo', function($type) {
        if ($type == 'acme-post')
            return YourModel::getMenuTypeInfo($type);
    });
}

在您的模型中,实现可能如下所示(此代码为简化此插件目的而简化,Rainlab.Pages 菜单需要更多数据)

public static function getMenuTypeInfo($type)
{
    $result = [];

    if ($type == 'acme-post') {
        $references = [];
        $posts = self::get();
        foreach ($posts as $post) {
            $references[$post->id] = $post->title;
        }
        $result = [
            'references'   => $references
        ];
    }

    return $result;
}

要在前端查看您的模型 SEO,您需要在您的页面中使用 SeoModel 组件

[seoModel]
pageType='acme-post'
pageProperty='post'

属性 pageType 应与您的模型属性 $seoPageType 相同

属性 pageProperty 通知插件在哪个页面属性中可以找到您的模型。它通常由组件在 onRun 方法中填充

public function onRun()
{
    $slug = $this->param('slug');

    $post = new YourModel;

    $post = YourModel::where('slug', $slug)->first();

    $this->page['post'] = $post;
}

如果您已经使用了一些模型字段用于 SEO 目的,您可以通过监听 zmark.seo.mapSeoData 事件来映射它们

Event::listen('zmark.seo.mapSeoData', function($type, $reference) {
    if ($type == 'acme-post') {
        return YourModel::mapSeoData($reference);
    }
});

在您的模型中,一个可能的实现可能如下所示

public static function mapSeoData($reference)
{
    $item = self::find($reference);

    $seo_data = [
        'title' => $item->title,
        'description' => str_limit(strip_tags($item->description), 155),
        'image' => $item->image,
    ];

    return $seo_data;
}

扩展您自己的模型

可以将一个 SEO 选项卡附加到您的模型,以便更轻松地访问 SEO 数据创建。您需要在您的模型类中实现 Seo Model Behavior

class Post
{
    public $implement = ['Zmark.Seo.Behaviors.SeoModel'];

    //required: menu item type that your plugin expects in pages.menuitem.getTypeInfo event
    public $seoPageType = 'acme-post';

    //optional: where to put the SEO tab, default is 'primary'
    public $seoTab = 'secondary';
}

此代码将在您的模型中插入一个新选项卡,用于预览、创建或编辑 SEO 数据。

网站地图生成器

此插件将基于所需的CMS页面和其他内容生成一个sitemap.xml文件。生成的站点地图遵循谷歌的多语言站点地图指南

查看站点地图

一旦配置了此插件生成的站点地图,可以通过访问网站基础路径相对的文件来查看。例如,如果网站托管在http://example.com,可以通过打开此URL来查看

http://example.com/sitemap.xml

您应将此URL添加到您的robots.txt文件中。

此站点地图在浏览器中不会渲染,这是一个已知问题。不幸的是,解决此问题的唯一已知方法会导致站点地图与谷歌搜索控制台不兼容。作为解决方案,还生成一个sitemap-debug.xml。此站点地图在浏览器中渲染正常,可以通过打开此URL来查看

http://example.com/sitemap-debug.xml

此站点地图仅用于调试目的,不要将此URL提交给谷歌搜索控制台。

管理站点地图定义

通过从SEO插件菜单中选择“站点地图”来管理站点地图。每个主题都有一个单独的站点地图定义,它将自动创建。

站点地图定义可以包含多个项目,每个项目都有多个属性。所有项目类型都有一些共同属性,某些属性取决于项目类型。常见的项目属性是优先级变更频率。优先级定义了该项目相对于站点地图中其他项目的优先级。变更频率定义了页面可能更改的频率。根据所选的项目类型,您可能需要提供项目的其他属性。以下描述了可用的属性。

参考

一个下拉列表,列出项目应引用的对象。列表内容取决于项目类型。对于静态页面项目类型,列表显示系统中定义的所有静态页面。对于博客分类项目类型,列表显示博客分类的列表。

CMS页面

此下拉列表适用于需要引用特殊CMS页面的项目类型。例如,博客分类项目类型需要托管blogPosts组件的CMS页面。此项目类型的CMS页面下拉列表将仅显示包含此组件的页面。

标准项目类型

可用的项目类型取决于已安装的插件,但有一些基本项目类型是默认支持的。

URL

此类型的项目是链接到特定固定URL的链接。这可能是一个内部页面的URL。此类型的项目没有其他属性,只有标题和URL。

CMS页面

此类型的项目引用CMS页面。页面应在下文描述的参考下拉列表中选择。

自定义项目类型

其他插件可以提供新的项目类型。其中一些是默认支持的。

Rainlab Pages插件

此插件提供两种新的项目类型

静态页面

此类型的项目引用静态页面。应在参考下拉列表中选择静态页面。

所有静态页面

此类型的项目扩展以创建指向主题中定义的所有静态页面的链接。

Rainlab Blog插件

此插件提供四种新的项目类型

博客分类

此类型的项目表示指向特定博客分类的链接。应在参考下拉列表中选择分类。此类型还需要选择输出博客分类的CMS页面

所有博客分类

此类型的项目扩展为创建指向所有现有博客分类的多个项目。此类型还需要选择一个CMS页面

博客文章

此类型的项目表示指向特定博客文章的链接。应在参考下拉列表中选择文章。此类型还需要选择输出博客文章的CMS页面

所有博客文章

此类型会扩展成多个项目,代表所有现有的博客文章。此类型还需要选择一个 CMS 页面

注册新的站点地图定义项目类型

站点地图插件与页面插件共享相同的注册项目类型的事件。有关更多信息,请参阅此插件提供的文档。

在通过 pages.menuitem.resolveItem 事件处理程序解析项目时,每个项目应返回数组中一个名为 mtime 的额外键。这应该是一个日期对象(见 Carbon\Carbon)或与PHP的 date() 函数兼容的时间戳值,表示链接最后一次修改的时间。

每个项目还应将所有备用语言(包括默认语言)的URL追加到名为 alternate_locale_urls 的数组中。

预期结果格式

Array (
    [url] => http://example.com/en/blog/article/article-slug-in-english
    [mtime] => '2018-12-01T14:08:09+00:00',
    [alternate_locale_urls] => Array (
        [en] => http://example.com/en/blog/article/article-slug-in-english
        [en] => http://example.com/es/blog/articulo/article-slug-in-spanish
    )
)

如何在您的模型中实现此操作的示例(简化版)

protected static function resolveMenuItem($item, $url, $theme)
{
    if ($item->type == 'acme-post') {

        $post = self::find($item->reference);

        $page = Page::loadCached($theme, $item->cmsPage);

        $defaultLocale = \RainLab\Translate\Models\Locale::getDefault()->code;

        $pageUrl = \Zmark\Seo\Models\Sitemap::getPageLocaleUrl($page, $post, $defaultLocale, ['slug' => 'slug']);

        $alternateLocales = array_keys(\RainLab\Translate\Models\Locale::listEnabled());

        if (count($alternateLocales) > 1) {
            foreach ($alternateLocales as $locale) {
                $result['alternate_locale_urls'][$locale] = \Zmark\Seo\Models\Sitemap::getPageLocaleUrl($page, $menuItem, $locale, ['slug' => 'slug']);
            }
        }

        $result['title'] = $post->title;
        $result['url'] = $pageUrl;
        $result['mtime'] = $post->updated_at;

        return $result;
    }

    return [$result];
}