Code Monkey home page Code Monkey logo

silverstripe-seo's Introduction

silverstripe-seo

An all-in-one SEO module for SilverStripe.

Note: Version 1.0.4 of this repository replaces version 1.0.3 of vulcandigital/silverstripe-seo.

Features

  • SEO Health Analysis in the Page Editor SEO Health Analysis
  • Automatic Facebook OpenGraph meta-tag generation (can override) Facebook SEO Control
  • Automatic Twitter meta-tag generation (can override) Twitter SEO Control
    • Also adds a TwitterAccountName field to SilverStripe\Security\Member which is used for the creator tag. The creator is recorded when a new page is created and their Twitter account name will be used for the meta tag

Example Meta Tags Output

<link rel="canonical" href="http://atmtanks.local/"/>
<meta property="og:title" content="Home"/>
<meta property="og:description" content="ATM Industrial Panel Tanks (ATM) specialises in tank builds, modifications and maintenance. ATM has performed significant tank refurbishments, re-lines and roof replacements for Government Hospitals, Power Stations, Food Process Companies, Mines and more."/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="http://atmtanks.local/"/>
<meta property="og:locale" content="en_GB" />
<meta property="og:site_name" content="ATM Industrial Panel Tanks" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Home"/>
<meta name="twitter:description" content="ATM Industrial Panel Tanks (ATM) specialises in tank builds, modifications and maintenance. ATM has performed significant tank refurbishments, re-lines and roof replacements for Government Hospitals, Power Stations, Food Process Companies, Mines and more."/>
<meta name="twitter:creator" content="@zanderwar"/>
<meta name="twitter:site" content="@vulcandigital" />
<meta property="article:published_time" content="2018-04-08T00:22:10+10:00" />
<meta property="article:modified_time" content="2018-04-16T21:52:52+10:00" />

If you think you can add something beneficial to this output, please don't hesitate to submit a PR or open an issue to discuss its addition. See CONTRIBUTING.md.

Requirements

See composer.json for details.

Installation

composer require quinninteractive/silverstripe-seo

Getting Started

The necessary extensions are automatically applied after installation of this module, and a dev/build.

Writing Your Own Analysis

Health analyses have been abstracted to give developers the ability to create their own analysis checks.

To do this, you simply need to create a new class that extends QuinnInteractive\Seo\Analysis\Analysis.

As an example, let's create a new analysis that checks to see if Hello World! is the title of the current page.

First create the following file:

mysite\code\Analysis\HelloWorldTitleAnalysis.php

<?php

namespace Vendor\Project\Analysis;

use QuinnInteractive\Seo\Analysis\Analysis;

class HelloWorldTitleAnalysis extends Analysis
{
    const FAILED = 0;
    const SUCCESS = 1;

    public function run()
    {
        if (!strstr($this->getPage()->Title, 'Hello World!')) {
            return static::FAILED;
        }

        return static::SUCCESS;
    }

    public function responses()
    {
        return [
            static::FAILED  => ['The string "Hello World!" does not appear in the page title', 'danger'],
            static::SUCCESS => ['Hoorah!!! "Hello World!" appears in the page title', 'success'],
        ];
    }
}

Then dev/build. You will immediately see this new analysis running in the CMS under the "SEO Health Analysis" accordion when editing any page, then change the title to include "Hello World" and you will notice the indicator will display success.

One thing to keep in mind is that the analysis always has access to the \Page object that it is running against via $this->getPage(), so your responses can also be dynamic.

If you have created an analysis and think it would be beneficial as an addition to this module then we urge you to submit a Pull Request and you will receive full credit for your work. See CONTRIBUTING.md.

Explained: run()

You must override this method as this is where you will perform all your checks, and then return with an integer respective of the keys you define in responses(). It's a good idea to use constants that represent those integers for readability

Explained: responses()

All analyses must override the responses() method to provide response messages and the response level (which is used for the indicator).

run() should return an integer that matches a key in the array that responses() returns, for example if run() were to return 1, then using the above example the message displayed would be Hoorah!!! "Hello World!" appears in the page title with an indicator level of success

The available indicator levels are: default, danger, warning, success which are grey, red, orange and green respectively.

You can optionally prevent certain levels from displaying in the content analysis tab. The following added to the above example would cause it to only display an entry if the indicator level is not of value success:

private static $hidden_levels = [
    'success'
];

Configuration Options

enable_creator_tag

By default, this module adds an extension to \SilverStripe\Security\Member that adds a single field named TwitterAccountName. If this is set, when this particular user creates a page, the twitter:creator meta tag will be generated with the Member's account name

You can disable this via YAML:

QuinnInteractive\Seo\Extensions\PageSeoExtension:
    enable_creator_tag: false

Length of meta description

The module has 2 configuration options pertaining to the length of the meta description. The sample YAML below demonstrates them with their default values. You don't have to make such a file unless you want different values from the defaults.

QuinnInteractive\Seo\Analysis\MetaDescAnalysis:
  meta_desc_target_length: 160
  meta_desc_too_long_threshold: 320

Other Options

Other options can be found in the private static variables in the following files. They can be overridden in YAML in the usual way.

  • PageHealthExtension.php
  • PageSeoExtension.php
  • SiteConfigSettingsExtension.php

Assumptions

This module assumes that you make use of the default Content field provided by \Page. If a specific page does not then you can specify one or multiple fields that contain your content.

They should be ordered in the correct order that they appear for the end user

In your \Page subclass you would have:

public function seoContentFields()
{
    return [
        'Content',
        'MyBlock.Title',
        'MyBlock.Content',
        'BottomTitle',
        'BottomContent',
    ];
}

In your \Page subclass you could add an updateCollateContentFields to provide custom content that is not possible with seoContentFields:

public function updateCollateContentFields($content) {
    // Content is an array of strings with content in the order in which they appear to the user
    $content[] = 'This is example content';
    return $content;
}

Roadmap (subject to change)

  • Finish implementing internationalisation to this module and its analyses
  • More content analyses
  • Given the ability to practically have content coming from anywhere on a SilverStripe page, the seoContentFields method was introduced to better improve content analysis by collating all content fields into a single string, this supports dot notation for has_one relationships, but may not (or does not) support has_many and many_many relationships at this time. Ideally moving forward we will want to use the DOM parser (partially implemented) and rely on this instead.
  • Finding community support to help improve and better this module for all SilverStripe users

License

BSD-3-Clause

Version

2.0.0

silverstripe-seo's People

Contributors

a2nt avatar guyvanbael avatar jianbinzhu avatar jsirish avatar kinglozzer avatar korthjp17 avatar mak001 avatar mattclegg avatar obj63mc avatar oddnoc avatar oliver-norden avatar phil-quinn avatar wilr avatar zanderwar 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

silverstripe-seo's Issues

URGENT: canonical link does not take into account any actions / ids / getvariables

The current implementation for the canonical link is not so good, because it removes any actions / ids / getvariables that often are an integral part of a page (e.g. www.e-commerce.com/products/show/12?version=3).

From what I can see, you could change this by changing the AbsoluteLink for a page, but that may have all sorts of other consequences.

Less method pollution in extensions

Methods like getArticleTags() may conflict with a users already existing methodology.

These methods should instead be decoupled into their own class, and used within the methods that must exist within the extension

template path is wrong (SS4.5.2)

When updating recipe-cms. Internal server error occurs with this message
2020-04-14 08:22:49] error-log.WARNING: E_USER_WARNING: None of the following templates could be found: QuinnInteractive\Seo\Forms\HealthAnalysisField in themes "Array ( [0] => silverstripe/admin:cms-forms [1] => $default ) " {"code":512,"message":"None of the following templates could be found: QuinnInteractive\\Seo\\Forms\\HealthAnalysisField in themes \"Array\n(\n [0] => silverstripe/admin:cms-forms\n [1] => $default\n)\n\"","file":"/Volumes/guySSD/webroot/carrewiel/vendor/silverstripe/framework/src/View/SSViewer.php","line":215} []
It seems dat the path to the template still has "Vulcan" in it. This should be changed into "QuinnInteractive" to fix it

Google Analytics & Pixel(s)

We kind of already called this an all-in-one and analytics does kind of fit into the category of SEO as you need analytics to track the performance of your SEO

Proposing to add a Google Analytics field to the SiteConfig within the already existing SiteConfig extension, can provide a configuration option to prevent displaying the field in the scenario a developer has commonly configured their own Google Analytics field and can't be bothered hiding theirs for whatever reason.

As a bonus, we can include the Google Analytics code within the meta tags that get generated so the dev would not have to modify any template file.

Other services like Facebook Pixel, Twitter Pixel & Snapchat Pixel could also be considered

not compatible with userforms 5.3.2

using it in conjunction with userforms 5.3.2 (on ss4.3.3)

This is what's in the error log.
Uncaught Exception BadMethodCallException: "Object->__call(): the method 'Fields' does not exist on 'SilverStripe\CMS\Model\SiteTree'" at /Users/xxx/Documents/webroot/xxxx/vendor/silverstripe/framework/src/Core/CustomMethods.php line 54 {"exception":"[object] (BadMethodCallException(code: 0): Object->__call(): the method 'Fields' does not exist on 'SilverStripe\CMS\Model\SiteTree' at /Users/xxx/Documents/webroot/xxx/vendor/silverstripe/framework/src/Core/CustomMethods.php:54)"} []

file_get_contents error

SilverStripe: 4.1.2
silverstripe-seo: 1.0.1

I get the following error when trying to view a page:

[Warning] file_get_contents(): php_network_getaddresses: getaddrinfo failed: Name or service not known

This is probably due to the fact that my website is running on project.localhost, and that name cannot be resolved since I don't have a hosts entry (Chrome forwards *.localhost domains to the localhost, so I don't need a hosts entry).

I believe it would also not work if my website was protected by basic auth, such as on a staging/test server, since there is no way of passing credentials.

It would be nice if there was a way to disable the health analysis, or pass additional options such as headers.

A problem with this module is causing CSS styling issues in the CMS Pages interface

The Problem

A problem with this module is causing the debug.css file to used on the CMS Pages (edit) interface which in turn causes styling issues

Steps to reproduce

  1. Login to the CMS (admin/)
  2. Travel to the Pages section using the left hand navigation (admin/pages/)
  3. Click on one of your pages in the Sitetree to edit it (admin/pages/edit/show/1)
  4. Look closely at the styles of the CMS interface

Screenshots

Before Installation

Here is how the CMS Pages edit interface should look (in SS4)
firefox-cms-pages-edit-styles-normal

After Installation

And here is what it currently looks like (some styling issues are highlighted in yellow).
The most noticeable difference is the font size and the left hand menu (which has items jutting out)
firefox-cms-pages-edit-styles-bug

The Stylesheet causing the issue

You can see that the debug.css file is being included. If you disable its styles using the developer tools the styling issues will be fixed.
firefox-console-debug-css

Possible Explanation

I originally brought this problem up over in the Silverstripe Slack channel (see this conversation) because I thought that it may be a framework bug (because debug.css is from the silverstripe framework). However when I discussed this issue with Andy he explained to me that this stylesheet is only included when the debug class (SilverStripe\Dev\Debug) is included or when an error has occurred.

tags not showing

Installed the module, added some data, but no opengraph tags are in the code. In Page.ss there's $MetaTags(false)
(ss4.5.2)
@oddnoc SOLUTION: in PageSeoExtension.php (line 75). Rename function getMetaTags to MetaTags
i created a pull request for this :-)

Breaks History Controller

When this module is installed it is not possible to view the individual history of a page as the following JS error occurs:
"bundle.js?m=1569294451:1 Uncaught (in promise) Error: Injector.get(): Component GoogleSearchPreview does not exist"

I resolved this in my project by adding the following to the getCMSFields in Page.php:
if(Controller::curr() instanceof HistoryViewerController){ $fields->removeByName('SEOHealthAnalysis'); }

There may be a better way as this removes the SEOHealthAnalysis from history completely.

Remove the need for seoContentFields

Remove the need for seoContentFields() by using the DOM parser to better analyse the page content.

We have to consider that majority of the time there is always duplicate content across the site, which would be the header, nav and footer. We can assume that these tags are used correctly and great content is not placed within them, and then remove these entirely before the analysis.

I mean to get anymore accurate than that you would need cross-page analysis to determine the probability of what is duplicate content and what is not.

Currently, seoContentFields does not support many_many or has_many relations so may very-greatly reduce the accuracy of the current analysis.

REFACTOR canonical creation to utilize MetaComponents method

Current implementation uses the MetaTags() extension method to alter the meta string. Alternatively, it's more reliable to use the MetaComponents() extension method as the meta tags are in an array, allowing for more consistent structure and easier, more reliable alterations to the metadata.

Similar update made in silverstripe/silverstripe-cms#2637

The underlying issue with the current implementation lies in VirtualPage which currently applies a canonical url to the CopyContentFrom page. The pull request noted above moves the canonical creation into MetaComponents() which should allow for a simple detection of an array key vs a regular expression of some type to prevent duplicate canonical tag generation in the case of VirtualPage (or any other custom page types that apply a canonical tag).

Relabel Facebook SEO out of the box?

The Facebook SEO tab name is potentially confusing - since the fields output standard Open Graph tags which apply to lot's of third-party providers I wonder if a better label is Open Graph fields?

server with request limit causes internal server error

when deploying to a server which has a limit on requests (to prevent infinite loops), i get an internal server error.
file_get_contents(myUrl/?stage=Stage): failed to open stream: HTTP request failed! HTTP/1.0 429 Too Many Requests\r\n in myUrl/public_html/vendor/vulcandigital/silverstripe-seo/src/Extensions/PageHealthExtension.php

Liveseo has nice stuff

googlesuggestfield.js – I think it's ideal for "set keyword focus". Some kind a stars / points – also will be nice.

EDIT: After change Title and publish – 'Search Preview' needs to be refreshed to see changes (F5).

Render content in process?

The Analysis class runs a HTTP request against the webserver to get the contents in https://github.com/vulcandigital/silverstripe-seo/blob/master/src/Analysis/Analysis.php#L164

I've got a few niggles with this: It isn't very performant (separate framework boot on every save request in CMS?), and it presumably can't read draft content because it's not performed in an authenticated session. So as an author, it appears that you can't get feedback on your draft content before you publish it, which is exactly when you'd want it, right?

Have you considered using Director::test() for this? It runs the request in process, and can account for stage=Stage.

Also, doing this with file_get_contents() isn't best practice - lots of systems have allow_url_fopen turns off for security reasons - it should use a HTTP client like Guzzle.

possible solution for rendering when using Elemental

I noticed that the analysis in PageHealthExtension didn't take into account any Elemental blocks. I couldn't see how you would use the seoContentFields configuration so I tried rendering with the current theme.

public function getRenderedHtml() {
... 
$current_themes = SSViewer::get_themes();  // get current CMS theme
Requirements::clear(); // we only want the HTML, not any of the js or css
SSViewer::set_themes(SSViewer::config()->uninherited('themes'));
$this->renderedHtml = $controllerName::singleton()->render($this->owner);
Requirements::restore(); // put the js/css requirements back when we're done
SSViewer::set_themes($current_themes);  // reset current CMS theme when we're done
...
}

Enforce indicator levels

An error should be thrown if an invalid indicator level is specified.

We should also introduce a hidden level, this would not make the config var $hidden_levels redundant as that can be used to hide warnings etc

Force trailing slash suggestion

It's good practice to ensure that there is consistency through the links for SEO and Analytical purposes.

Links like /about-us and /about-us/ will register as two different pages (at least from a Google Analytics point of view).

As such we should add the axllent/silverstripe-trailing-slash module as a suggestion to the composer.json

BUG Form classes reference vulcandigital in the JS Requirements

Throws the following error when loading a page in the CMS:

Uncaught InvalidArgumentException: Can't find module 'vulcandigital/silverstripe-seo', the composer.json file may be missing from the modules installation directory

The requirements should reference quinninteractive vs. vulcandigital.

Affected files include HealthAnalysisField and GoogleSearchPreview

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.