Page 1 of 1

v1.4.9.3 > SEO url solution against duplicate content

Posted: Tue Jan 18, 2011 3:28 am
by wusadesign
I like Opencart, only I noticed that when I visit the 'home' page, the products visible in for example the latest products block has an url only with it's keyword in it without the category path.
Now I know that a product can have multiple categories, but for my webshop I want to create a sitestructure with only one url to a page. Duplicate content is also blackhat SEO, so I want to prevent it as much as possible.

I don't know if that which I made is the most efficient because I am not familair with Opencart, so feedback is welcome.

Open the following file from the root: catalog/model/tool/seo_url.php

After:

Code: Select all

 class ModelToolSeoUrl extends Model {
Put the following piece of code:

Code: Select all

/*begin mod*/
  public function get_cat_alias($cid)
  {
    $cid=intval($cid);
    $query='
      SELECT
        c.parent_id,
        a.keyword
      FROM
        '.DB_PREFIX.'category AS c,
        '.DB_PREFIX.'url_alias AS a,
        '.DB_PREFIX.'product_to_category AS pc
      WHERE
        c.category_id='.$cid.' && a.query="category_id='.$cid.'"
      LIMIT 1
    ';
    $result=$this->db->query($query);
    $results=array();
    foreach($result->rows as $row)
    {
      if(intval($row['parent_id'])!==0)$results[]=$this->get_cat_alias($row['parent_id']);
      if(isset($row['keyword']))$results[]=$row['keyword'];
    }
    return $results;
  }
  function output_cat_alias($array)
  {
    $result=array();
    foreach($array as $keyword)
    {
      if(is_array($keyword))
      {
        $result[]=$this->output_cat_alias($keyword);
      }else
      {
        $result[]=$keyword;
      }
    }
    return implode('/',$result);
  }
/*end mod*/
And after:

Code: Select all

if (($key == 'product_id') || ($key == 'manufacturer_id') || ($key == 'information_id')) {
Put the following piece of code:

Code: Select all

/*begin mod*/
          if($key == 'product_id')
          {
            $query='
              SELECT
                c.parent_id,
                c.category_id
              FROM
                '.DB_PREFIX.'category AS c,
                '.DB_PREFIX.'url_alias AS a,
                '.DB_PREFIX.'product_to_category AS pc
              WHERE
                pc.product_id='.$value.' &&
                pc.category_id=c.category_id
              LIMIT 1
            ';
            $cat_current=$this->db->query($query);
            $query='
              SELECT
                a.keyword
              FROM
                '.DB_PREFIX.'url_alias AS a
              WHERE
                a.query="category_id='.$cat_current->row['category_id'].'"
              LIMIT 1
            ';
            $cat_current_key=$this->db->query($query);
            $url=$this->get_cat_alias($cat_current->row['parent_id']);
            $url=array(0=>$url,1=>$cat_current_key->row['keyword']);
            $url='/'.$this->output_cat_alias($url);
          }
/*end mod*/

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Tue Jan 18, 2011 3:32 am
by Chones
I don't know about your code, but you didn't need to do anything. Sorry if you've wasted your time.

OpenCart uses the rel=canonical meta tag to make sure the search engines only index www.yoursite.com/product-name even if it is in multiple categories.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Tue Jan 18, 2011 10:33 pm
by wusadesign
Thank you for the tip. I do prefer my modification at my webshop, in my opinion the breadcrumbs are also nicer that way (instead of home > product), if it is not for SEO than for the usability :)

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Wed Jan 19, 2011 4:53 am
by Chones
I completely agree, as long as you only have products in one category. I have products in multiple categories and I wouldn't want someone buying a gift for his wife to see the breadcrumbs as

Code: Select all

Home > Gifts > For Him > Product

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Tue Mar 01, 2011 11:31 pm
by scroorage
Hi, I have modified the code using wusadesigns tutorial. It has helped. Thank you :)
But when I open the product It displays the URL like: http://www.domainname.com//categoryname/productname

Could anybody pls advise me how to ged rid of the double slash in url, there should be just single after domain name.

Thank you.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Wed Mar 02, 2011 9:43 am
by philbydevil
I have a similar problem to scroorage, but my category isn't showing. Instead it's just:

http://www.domainname.com//productname

Also, I noticed that even with this code enabled, I can still access the product at the old url (ie. without the category). This is good because I know Google has indexed my pages like this, but won't this lead to duplicate content?

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Wed Mar 02, 2011 9:01 pm
by bald
I tried to convert your mod to the vQmod (1.0.8 ) file and am getting following error (OC v1.4.9.3):

Notice: Undefined index: keyword in C:\wamp\www\vqmod\vqcache\vqcache_catalog_model_tool_seo_url.php on line 87

UPDATE:

OK, I solved the above -- there was one category missing its SEO Keyword.
But anyways still having "double slash" issue as guys mentioned earlier. I guess this may be related to categories being not equally deep.
I have a few main categories where some of them are just one-level-deep and the others are two-levels-deep.

UPDATE 2:

It seems like there's an issue with arrays indexes. Just FYI:

Find:

Code: Select all

return implode('/',$result);
BEFORE, add:

Code: Select all

foreach ($result as $rs) echo $rs."<br />";
And take a look what $result contains.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Wed Mar 02, 2011 10:10 pm
by scroorage
Hi, I have fixed it. All you need to do is to remove / from the end of the first part of the code.
Instead of:

Code: Select all

return implode('/',$result);
  }
/*end mod*/
Should be:

Code: Select all

return implode('',$result);
  }
/*end mod*/
It works for me :)
Hope it will help

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Wed Mar 02, 2011 10:26 pm
by bald
Your solution works as long as you have only up to one level deep subcategory tree. Having two or more subcategories results in having urls like: Category/SuboneSubtwoSubthree

UPDATE:
I don't know where's the core of the problem, but we can always clean up the final $url var:

Find:

Code: Select all

$url='/'.$this->output_cat_alias($url);
Replace with:

Code: Select all

$url=$this->output_cat_alias($url); //send $url to the function without any slash in front
$url = preg_replace("/^[\/]/", "", $url); //remove unwanted slash (if exists)
$url = "/".$url; //then add wanted slash (just one)
I tried it on 4 subcategories and it's OK for me. Try for yourself.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Thu Mar 03, 2011 5:29 am
by scroorage
Thank you. It works for me too ;D

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Sat May 21, 2011 9:40 am
by Kazak Uralsky
Hi guys, this helped me too. Thanks a lot.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Mon Jun 18, 2012 1:53 am
by kgkaraoke
wusadesign wrote:I like Opencart, only I noticed that when I visit the 'home' page, the products visible in for example the latest products block has an url only with it's keyword in it without the category path.
Now I know that a product can have multiple categories, but for my webshop I want to create a sitestructure with only one url to a page. Duplicate content is also blackhat SEO, so I want to prevent it as much as possible.

I don't know if that which I made is the most efficient because I am not familair with Opencart, so feedback is welcome.

Open the following file from the root: catalog/model/tool/seo_url.php

After:

Code: Select all

 class ModelToolSeoUrl extends Model {
Put the following piece of code:

Code: Select all

/*begin mod*/
  public function get_cat_alias($cid)
  {
    $cid=intval($cid);
    $query='
      SELECT
        c.parent_id,
        a.keyword
      FROM
        '.DB_PREFIX.'category AS c,
        '.DB_PREFIX.'url_alias AS a,
        '.DB_PREFIX.'product_to_category AS pc
      WHERE
        c.category_id='.$cid.' && a.query="category_id='.$cid.'"
      LIMIT 1
    ';
    $result=$this->db->query($query);
    $results=array();
    foreach($result->rows as $row)
    {
      if(intval($row['parent_id'])!==0)$results[]=$this->get_cat_alias($row['parent_id']);
      if(isset($row['keyword']))$results[]=$row['keyword'];
    }
    return $results;
  }
  function output_cat_alias($array)
  {
    $result=array();
    foreach($array as $keyword)
    {
      if(is_array($keyword))
      {
        $result[]=$this->output_cat_alias($keyword);
      }else
      {
        $result[]=$keyword;
      }
    }
    return implode('/',$result);
  }
/*end mod*/
And after:

Code: Select all

if (($key == 'product_id') || ($key == 'manufacturer_id') || ($key == 'information_id')) {
Put the following piece of code:

Code: Select all

/*begin mod*/
          if($key == 'product_id')
          {
            $query='
              SELECT
                c.parent_id,
                c.category_id
              FROM
                '.DB_PREFIX.'category AS c,
                '.DB_PREFIX.'url_alias AS a,
                '.DB_PREFIX.'product_to_category AS pc
              WHERE
                pc.product_id='.$value.' &&
                pc.category_id=c.category_id
              LIMIT 1
            ';
            $cat_current=$this->db->query($query);
            $query='
              SELECT
                a.keyword
              FROM
                '.DB_PREFIX.'url_alias AS a
              WHERE
                a.query="category_id='.$cat_current->row['category_id'].'"
              LIMIT 1
            ';
            $cat_current_key=$this->db->query($query);
            $url=$this->get_cat_alias($cat_current->row['parent_id']);
            $url=array(0=>$url,1=>$cat_current_key->row['keyword']);
            $url='/'.$this->output_cat_alias($url);
          }
/*end mod*/
NO, it DOESN'T work, and if, as you state, you're unfamiliar with Opencart, then why the heck are you posting code for it?

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Mon Jun 18, 2012 2:09 am
by kgkaraoke
Chones wrote:I don't know about your code, but you didn't need to do anything. Sorry if you've wasted your time.

OpenCart uses the rel=canonical meta tag to make sure the search engines only index http://www.yoursite.com/product-name even if it is in multiple categories.
Why is the product-name in multiple categories in the first place?
This is like putting a Band Aid on bad code, and this sloppy coding made its way into 1.5.X.X even though Daniel was well aware of the issue. The url of a product should grow directly out of the home directory. If I have a category named Widgets with a url of http://www.mystore.com/Widgets and on the Widgets page I have a product named Pigets, then the url of Pigets should ONLY be http://www.mystore.com/Pigets and NOT http://www.mystore.com/Widgets/Pigets.

And "Related Products" only screws things up more. If product-A is related to Product-B, then searching for one of the products will pull-up TWO listings, one for Product-A and one for Product-B. Obviously the OpenCart "team" isn't familiar with seo.

It pains me to state this, but I can identify an OpenCart store by the URL structures that appear in the search engines. This is terrible.

Re: v1.4.9.3 > SEO url solution against duplicate content

Posted: Mon Jun 18, 2012 2:46 am
by kgkaraoke
bald wrote:Your solution works as long as you have only up to one level deep subcategory tree. Having two or more subcategories results in having urls like: Category/SuboneSubtwoSubthree

UPDATE:
I don't know where's the core of the problem, but we can always clean up the final $url var:

Find:

Code: Select all

$url='/'.$this->output_cat_alias($url);
Replace with:

Code: Select all

$url=$this->output_cat_alias($url); //send $url to the function without any slash in front
$url = preg_replace("/^[\/]/", "", $url); //remove unwanted slash (if exists)
$url = "/".$url; //then add wanted slash (just one)
I tried it on 4 subcategories and it's OK for me. Try for yourself.
You're dreaming.
It doesn't work, period.
If you have a category named "Widgets" and a product named "Pigets" then you will have TWO URLs,
http://www.mystore.com/Widgets/Pigets as well as http://www.mystore.com/Pigets

You stated:
"I don't know where's the core of the problem"

Well, then, how on Earth can you come up with a "solution"?