Code Tweaks Add Dynamic Canonical URL Tags to Sngine Site

Status
Not open for further replies.

proxybunker

Administrator
Senior Administrator
Support Technician
Hosting Technician
Points 28
Solutions 0
Purpose: The canonical tag (<link rel="canonical" href="...">) tells search engines: "This is the definitive URL for this page." It solves the problem of the same or similar content being reachable from multiple URLs.

When duplicate URLs happen (very common):
- https://example.com/blogs vs https://www.example.com/blogs (www vs non-www)
- https://example.com/blogs vs https://example.com/blogs?utm_source=twitter (tracking parameters)
- https://example.com/blogs vs http://example.com/blogs (http vs https)
- Category/tag pages that show the same posts in different ways

What happens without it: Google sees these as separate pages with identical content. It picks one
version as "canonical" on its own — often the wrong one. The consequences:
- Link equity (ranking power) gets split across the duplicates instead of consolidating on one URL
- Google may index the wrong version
- In your case, Google decided your site was a copy of itself and tanked your rankings to 100+

What the tag does: It puts you in control. You tell Google which URL is the real one, and it
consolidates all ranking signals onto that single URL.

Is it needed on every site? Practically yes. Even a simple 5-page site can have duplicate URL issues
(www vs non-www alone creates duplicates). Large dynamic sites like yours (with profiles, blogs,
groups, etc.) absolutely need it — the more URL patterns, the more chances for duplicates.

Want me to proceed with implementing the plan?

Here's how the logic works step by step:

1. When a visitor loads any page (say https://yoursite.com/profile/john), the PHP function
page_header() runs automatically as part of rendering every page on your site.

2. It reads the current URL path from $_SERVER['REQUEST_URI'] — this is the part after your domain:
/profile/john

3. It strips query parameters using parse_url(). So if someone arrives via
https://yoursite.com/profile/john?utm_source=twitter, it extracts only /profile/john and discards
the ?utm_source=twitter part.

4. It combines your site's base URL + the path:
SYS_URL (= https://yoursite.com) + /profile/john
= https://yoursite.com/profile/john

5. It passes this to the template, which outputs:
<link rel="canonical" href="https://yoursite.com/profile/john" />

Different pages automatically get different canonicals:

┌─────────────────────┬─────────────────────────────────────────┐
│ Page visitor loads │ Canonical tag output │
├─────────────────────┼─────────────────────────────────────────┤
│ /profile/john │ https://yoursite.com/profile/john
├─────────────────────┼─────────────────────────────────────────┤
│ /blogs/my-post/42 │ https://yoursite.com/blogs/my-post/42
├─────────────────────┼─────────────────────────────────────────┤
│ /groups/photography │ https://yoursite.com/groups/photography
├─────────────────────┼─────────────────────────────────────────┤
│ /events/music-fest │ https://yoursite.com/events/music-fest
├─────────────────────┼─────────────────────────────────────────┤
│ / (homepage) │ https://yoursite.com/
└─────────────────────┴─────────────────────────────────────────┘

The only manual input needed is SYS_URL in your config file — which you already set when you
installed Sngine. Everything else is automatic.

Want me to proceed with the implementation?

Changes

File 1: includes/functions.php

Find this function (around line 7269):
PHP:
  function page_header($title, $description = '', $image = '')
  {
    global $smarty, $system;
    $description = ($description != '') ? $description : __($system['system_description']);
    if ($image == '') {
      if ($system['system_ogimage']) {
        $image = $system['system_uploads'] . '/' . $system['system_ogimage'];
      } else {
        $image = $system['system_url'] . '/content/themes/' . $system['theme'] .
  '/images/og-image.jpg';
      }
    }
    $smarty->assign('page_title', $title);
    $smarty->assign('page_description', $description);
    $smarty->assign('page_image', $image);
  }

  Replace with:

  function page_header($title, $description = '', $image = '')
  {
    global $smarty, $system;
    $description = ($description != '') ? $description : __($system['system_description']);
    if ($image == '') {
      if ($system['system_ogimage']) {
        $image = $system['system_uploads'] . '/' . $system['system_ogimage'];
      } else {
        $image = $system['system_url'] . '/content/themes/' . $system['theme'] .
  '/images/og-image.jpg';
      }
    }
    $smarty->assign('page_title', $title);
    $smarty->assign('page_description', $description);
    $smarty->assign('page_image', $image);

    /* generate canonical URL */
    $page_canonical = '';
    if (isset($_SERVER['REQUEST_URI'])) {
      $request_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
      if ($request_path !== null && $request_path !== '') {
        $skip_prefixes = ['/admincp', '/modcp', '/admin.php', '/moderator.php'];
        $is_control_panel = false;
        foreach ($skip_prefixes as $prefix) {
          if (strpos($request_path, $prefix) === 0) {
            $is_control_panel = true;
            break;
          }
        }
        if (!$is_control_panel) {
          $page_canonical = SYS_URL . $request_path;
        }
      }
    }
    $smarty->assign('page_canonical', $page_canonical);
  }

File 2: content/themes/default/templates/_head.tpl

Find this section (lines 21-33):
HTML:
      <!-- OG-Meta -->
      <meta property="og:title" content="{$page_title|truncate:70}" />
      <meta property="og:description" content="{$page_description|truncate:300}" />
      <meta property="og:site_name" content="{__($system['system_title'])}" />
      <meta property="og:image" content="{$page_image}" />
      <!-- OG-Meta -->

      <!-- Twitter-Meta -->
      <meta name="twitter:card" content="summary_large_image">
      <meta name="twitter:title" content="{$page_title|truncate:70}" />
      <meta name="twitter:description" content="{$page_description|truncate:300}" />
      <meta name="twitter:image" content="{$page_image}" />
      <!-- Twitter-Meta -->

  Replace with:

      <!-- OG-Meta -->
      <meta property="og:title" content="{$page_title|truncate:70}" />
      <meta property="og:description" content="{$page_description|truncate:300}" />
      <meta property="og:site_name" content="{__($system['system_title'])}" />
      <meta property="og:image" content="{$page_image}" />
      <meta property="og:url" content="{if $page_canonical neq ''}{$page_canonical}{else}{$system['system_url']}{/if}" />
      <!-- OG-Meta -->

      <!-- Canonical -->
      {if $page_canonical neq ''}
        <link rel="canonical" href="{$page_canonical}" />
      {/if}
      <!-- Canonical -->

      <!-- Twitter-Meta -->
      <meta name="twitter:card" content="summary_large_image">
      <meta name="twitter:title" content="{$page_title|truncate:70}" />
      <meta name="twitter:description" content="{$page_description|truncate:300}" />
      <meta name="twitter:image" content="{$page_image}" />
      <!-- Twitter-Meta -->
Those are the only two changes. Want me to apply them?

ways to test the changes have taken effect:

Quick local check — View page source on any public page on your site and search for canonical. You should see exactly one <link rel="canonical"> tag with the correct URL.

Online tools:

1. Google Rich Results Test — https://search.google.com/test/rich-results — Enter any public page URL and it will show if the canonical tag is detected

2. Google Search Console URL Inspection — If your site is verified in Search Console, use the URL Inspection tool on any page. It will show the canonical Google detects

3. Screaming Frog SEO Spider (free for up to 500 URLs) — https://www.screamingfrogseoseo.com/ — Crawls your entire site and shows all

canonical tags in a spreadsheet view, plus flags any issues
4. Hreflang Tags Testing Tool — https://technicalseo.com/tools/hreflang/ — Also checks canonical tags among other things

Most useful for your case: Screaming Frog. It will crawl your whole site and instantly show you whether every page has its own unique canonical, whether any are missing, and whether any are duplicates. That's the fastest way to confirm the implementation is correct across all pages.
 
Status
Not open for further replies.

Donate: Campaign

Total amount
$0.00
Goal
$60.00

AdSense

Back
Top