Blog

DataObjects and GoogleSitemaps

Posted by Roland Lehmann on 8 June 2011 | 4 Comments

Tags: ,

Googlesitemaps is a great module for SilverStripe. It is so important to SilverStripe's team that they deliver it with the standard download package. The sitemap is an important cornerstone in SEO, and SEO is vital for an ecommerce website.

What's the big deal?

The module creates an (virtual) XML-file in the installation root. The file delivers all viewable pages created in the backend as XML elements.

The thing is: SilverCart's products are DataObjects and do not have a backend page. There is a detail page that shows product details depending on an ID segment in the url. It took me one hour to modify the googlesitemaps module to show our product detail pages to each viewable product.

When I contacted SilverStripe's core developer Will Rossiter to add me changes to the modules code, he asked mo to find a solution that would be applicable to any DataObject. That way eg. forum threads could be added to the sitemap. With the help of Sebastian I found that solution in short time (the truth is: He did it on his own while I was sitting next to him).

The code

I submitted my changes to the file GoogleSitemap.php to the github repository as a pull request. I hope they find their way into the standard code soon. Meanwhile you may get them from my repo:

https://github.com/rlehmann/silverstripe-googlesitemaps

But thats not enough. The google sitemap needs a link to each item. This is called in the template /googlesitemaps/templates/GoogleSitemap.ss as AbsoluteLink. Your DataObject needs an additional method. For our SilvercartProduct it looks like this:

    /**
     * Returns the link to this product with protocol and domain
     * 
     * @return string the absolute link to this product
     * @author Roland Lehmann , Sebastian Diel 
     * @since 6.6.2011 
     */
    public function AbsoluteLink() {
        return Director::absoluteURL($this->Link());
    }
 

Furthermore define a method canView(). Ours uses the SilvercartProduct::get() wrapper to determin if the product is viewable:

    /**
     * Is this product viewable in the frontend?
     * 
     * @param Member $member the current member
     * 
     * @author Roland Lehmann 
     * @copyright 2011 pixeltricks GmbH
     * @since 6.6.2011
     * @return bool 
     */
    public function canView($member = null) {
        parent::canView($member);
        $publishedProduct = SilvercartProduct::get("`ID` = $this->ID");
        if ($publishedProduct) {
            return true;
        } else {
            return false;
        }
    }
 

Now you still need to tell the system which DataObject to add to the sitemap. We have a static method that should be called inside your project's config.php:

if (method_exists('GoogleSitemap', 'registerDataObject')) {
    GoogleSitemap::registerDataObject('SilvercartProduct');
}
 

The call to method_exists() makes sure that your googlesitemap module has our changes. You may pass the change frequency (daily, weeky, monthly, ...) as a second parameter. It's default value is "monthly".

Post your comment

Comments

  • Ramon Kupper, 08/06/2011 11:20pm (3 years ago)

    Thanks for fixing this issue. A proper Google Sitemap is invaluable for SEO.

    Great job!

  • Invader_Zim, 08/06/2011 11:24pm (3 years ago)

    Hi,
    i've read your thread on the official forum and was like: "Yay!"
    Now i read this article and i'm all like "Awesome!!!". Thank you for that, and i hope it's pulled soon.
    Cheers
    Christian

  • Roland Lehmann, 13/06/2011 1:30pm (3 years ago)

    After some communication with Will Rossiter from SilverStripe I added Priority as a thrid parameter to GoogleSitemap::registerDataObject().

  • Kyle, 21/04/2012 3:43pm (2 years ago)

    I've downloaded the latest version of Sitemaps and it works like a charm with my data objects. Question - should the 'Google Sitemaps' tab be showing up when I view/edit my data object, as it does on pages? If not, is there a way to achieve this? It would be nice to be able to set priority on a per-object level if possible.