Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Canonical tags for SubsiteVirtualPage point to wrong domain. #466

Open
davejtoews opened this issue Jun 2, 2021 · 1 comment
Open

Canonical tags for SubsiteVirtualPage point to wrong domain. #466

davejtoews opened this issue Jun 2, 2021 · 1 comment

Comments

@davejtoews
Copy link

SubsiteVirtualPage inherits the MetaTags method from Virtual Page

This generates a <link rel="canonical"> tag in the page head pointing to the original copy of the page. However the method does not seem to account for the possibility of multiple domains.

If I have an original page at http://example.com/original and a subsite virtual page at http://subsite.example.com/virtual, the virtual page ends up with a canonical tag linking to http://subsite.example.com/original -- a page that may or may not exist, and if it does exist, it's the wrong content.

In Silverstripe 4.7.1 the canonical link is a relative path, which is why it always points to the current domain/subdomain.

It looks like changes are coming to VirtualPage that will affect how this works: silverstripe/silverstripe-cms@85c3b10

I have not directly tested the changes however I don't believe they will solve the problem. The new method does replace Link() with AbsoluteLink() but I believe this will result in a full link path still pointing to the current domain rather than the correct subdomain for the original page. What I have tested is just swapping Link() for AbsoluteLink() in my local copy of VirtualPage.php and the result is a full, incorrect path in the canonical tag.

@davejtoews
Copy link
Author

If anyone else is running into this issue this is the hacky solution I'm using:

Define variable in .env

MAIN_SITE_DOMAIN="example.com"

There doesn't seem to be another way of determining the correct path for links on the main site other than hard coding it somewhere. Doing this in .env makes it possible to configure this per environment.

Define alternate MetaTags method in Page.php with an extension hook

    public function SubsiteMetaTags($includeTitle = true)
    {
        $tagString = $this->MetaTags($includeTitle);

        $extendedResponse = $this->extend('updateSubsiteMetaTags', $tagString);
        $tagString = count($extendedResponse) ? $extendedResponse[0] : $tagString;

        return $tagString;
    }

This is necessary to be able to modify the tags after VirtualPage has added a canonical tag

Use extension hook in VirtualPageExtension.php

    public function updateSubsiteMetaTags($tagString)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        // set error level
        $internalErrors = libxml_use_internal_errors(true);

        // wraps in div because output returns single node
        $dom->loadHTML('<div>' . $tagString . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        // Restore error level
        libxml_use_internal_errors($internalErrors);

        $nodes = $dom->getElementsByTagName('link');
        foreach ($nodes as $node) {
            if ($node->getAttribute('rel') === 'canonical') {
                if ($this->owner->CopyContentFrom()->Subsite()->exists()) {
                    $link = Director::absoluteURL($this->owner->CopyContentFrom()->alternateAbsoluteLink());
                } else {
                    $link = '//' . Environment::getEnv('MAIN_SITE_DOMAIN') . $this->owner->CopyContentFrom()->Link();
                }

                $node->setAttribute('href', $link);
            }
        };

        // trims wrapping div
        return substr(substr($dom->saveHTML(), 5), 0, -7);
    }

Use a yml config to apply this extension to the VirtualPage class

Use in template

Replace $MetaTags in Page.ss with $SubsiteMetaTags


This solution wouldn't work as a PR, it's predicated on the broken canonical tag already being there. But it seems as though any solution will have to incorporate something like the .env variable above in order to properly link to pages on the main site.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants