<?php
defined('C5_EXECUTE') or die(_("Access Denied."));
class SiteNavigationHelper extends NavigationHelper {
/**
* Returns a link to a page
* @param Page $cObj
* @return string $link
*/
public function getLinkToCollection(&$cObj, $appendBaseURL = false, $ignoreUrlRewriting = false) {
// basically returns a link to a collection, based on whether or we have
// mod_rewrite enabled, and the collection has a path
$dispatcher = '';
if (!defined('URL_REWRITING_ALL') || URL_REWRITING_ALL == false) {
if ((!URL_REWRITING) || $ignoreUrlRewriting) {
$dispatcher = '/' . DISPATCHER_FILENAME;
}
}
if ($cObj->getCollectionPath() != null) {
$link = DIR_REL . $dispatcher . $cObj->getCollectionPath() ;
} else {
$_cID = ($cObj->getCollectionPointerID() > 0) ? $cObj->getCollectionPointerOriginalID() : $cObj->getCollectionID();
$link = DIR_REL . '/' . DISPATCHER_FILENAME . '?cID=' . $_cID;
}
if ($appendBaseURL) {
$link = BASE_URL . $link;
}
return $link;
}
}
?>
Originally posted by DavidMIRV in the Forums
Edited with some updates by andrew
This Google Webmaster blog post basically explains that having two urls point to the same content is not ideal for users or googlebot. I have often found that you can also get SEO dillution through content duplication over the same two similar urls (site.com/url and site.com/url/). concrete5 will render the same page at yoursite.com/index.php/about/ and yoursite.com/index.php/about. There is however a simple fix you can implement in concrete5 to stop this behavior and improve your site's SEO friendliness.
Enable a Custom Redirect
First, create config/site_post.php in your local config/ directory. This is a custom file that lets your site do some work every time it is accessed. Perfect for what we need.
I added the following code to detect 301 redirect the 'bad' URL's
<?php
if ($_SERVER['REQUEST_URI'] != '/' && preg_match('#/$#',$_SERVER['REQUEST_URI']))
{
$newuri = preg_replace('#/$#','',$_SERVER['REQUEST_URI']);
Header( "HTTP/1.1 301 Moved Permanently" );
Header( "Location: ". BASE_URL. $newuri);
}
?>
This will force only one instance of the URL to be the truly canonical one.
Additionally, if you'd like to change the navigation helper which builds these links to use the ones without ending slashes, you can employ this code. (Editor's Note: It'd probably be simpler to change the above code to treat the pages with trailing slashes as the canonical URLs, and leave this code unchanged, but this will work as well, and is useful for those who prefer links without trailing slashes.)
Override and Extend the Navigation Helper
First, create navigation.php in your local empty helpers/ directory. Then, paste the following content into it:
This should fix any calls to the core API for getting the URL and the sitemap.xml generation of the page link
Simple eh? Thats my motto - keep it simple. I was originally concerned about this code effecting single page controller arguments but thus far in my testing in the last month I haven't discovered anything. Let me know if you do!
- Replace the default font in the Elemental theme
- Making Elemental themes image slider title and description responsive
- Add a Font Face kit
- Creating a Full screen Header Image for the Anitya Theme
- How to add Orders to Razor Commerce Programmatically
- Add new entries to the "Social Links" Dashboard page
- Demo Page for Dashboard Addon
- How to create modal dialogs on dashboard single pages in packages
- Record the page ID in form responses
- Get an addon or theme ready for the marketplace
- Logical OR filtering for multi select attributes
- How to copy the Elemental theme to use as a base for new themes
- Get block path from block controller
- Make all YouTube embeds responsive
- File Permission Errors: How to spot and fix these errors in Linux
- Global Areas for each language section
- Use Bootstrap Tabs in frontend theme without an add-on
- Package Install Notes
- Get ecommerce product name and description for use in custom blocks
- Getting the URL for a block or package tool
- Process to know logged in user from block
- Third party assets in packages
- How to check if you are in edit mode or not
- Using a Custom URL Attribute for External Redirection
- Windows IIS7 Pretty URL
- Missing and hard to find pages on concrete5.org
- Programmatically testing permissions on pages for a given user/group
- Speed up redirect for Internationalization add on
- Add rel="nofollow" to your pagination links
- Protect File Url's : Part 1
- Magic Data Page List Teaser functionality for Page List Plus
- Protect File Url's : Part 2
- Create large numbers of page versions for testing
- Load template specific assets
- Get the Package Path in a Dashboard Single Page Controller
- Internationalization Add-on and a Home page for every language!
- Responsive Video Embed
- Extending Area Model and Deleting Areas
- My site isn't sending email!
- Changing parent page, & keeping old child URL's active
- Easily scope CSS using LESS or SASS
- How to run multiple concrete5 installs on a single core (Apache vhost config)
- What version of concrete5 am I using?
- Check prerequisites before installing a package
- Hardcode edit permissions for areas
- Multilingual in combination with a tools file within a package
- Inherit between blocks in the same package
- Reverse Stack Content Display Order
- Make a package update automatically available
- How to use the Interactive Shell to run code against concrete5 from a console
- How to Extract Blocks from a Stack and Randomly Display Them
- Low profile caching method
- Delete Multiple pages
- Programtically Give a Group "Access User Search" Permission
- Reliable package install & updates
- Magic Data Enabling a Page List
- Programmatically creating and adding users to Groups
- Use tokens to secure transactions
- Filtering a list of states based on selected country
- Write a Queueable Job in concrete5 5.6.2+
- Overriding profile pages from within a package
- Style a file input field
- Overriding single pages within a package theme
- Integrate Concrete Wall with Magic Data using Universal Content Puller
- Access virtual hosts from any device using xip.io
- Concrete 5 in an AWS load balanced cluster
- Sort out file permissions in bulk
- nginx (with fastcgi_cache) + php5-fpm
- How to add composer functionality to your custom block
- Concrete 5 in an AWS load balanced cluster - 2
- Search block without results
- Separating environment specific configurations
- Styling the pagination
- Save and retrieve arrays of data
- Formatting numbers
- Send administrators to the dashboard upon login
- Add tracking code to page headers sitewide, or on just one page
- MyISAM Vs InnoDB
- Prevent an HTML block from interfering with edit mode.
- Format an edit mode marker
- Check If Block is Being Displayed in the Stack Dashboard Edit Page
- Core-Commerce Product pagination bunched up together
- Programmatically setting advanced permissions
- Organise your concrete5 web space for risk free upgrades
- Adding the Page Name to HTML Markup as an ID
- Display number of page views count
- Change Locale with PHP
- Translation of some special items
- Grant Dashboard access to specific groups
- Obtain a Unique Identifier for a Block
- Display User Attribute as Full Name, Image, and a Custom Link on every Blog Post
- Adapt jQuery event handlers to old concrete5 versions
- Edit the e-mail sent by form block
- 10 Useful Tools You Probably Didn't Know Existed, Volume 3
- Forbidden Functions
- Install C5 using MySQL InnoDB tables
- The block does not work!
- Allow HTML5 tags in TinyMCE
- Internationalization and the t() functions family
- Integrate Magic Data with Avatar add-on, and Facebook social plugins
- Translate your package
- Overriding Guestbook Entry Order in 5.6+
- Cope with old versions of Internet Explorer
- Integrate Magic Data and Page Attributes to display different images in areas or pages.
- Very Simple concrete5 theme
- Profiling your concrete5 site with Xdebug and WinCacheGrind
- Skip the file manager for specific set uploads
- Integrating Magic Data Tokens with other blocks
- Exclude Admin / Super user from user list
- Scripting Your Site Into Maintenance Mode
- Subvert the JavaScript run by the Page Selector helper
- Extend Core Statistic system
- Flushing your own cache
- BackPorting to older c5 version
- Copy a Language Tree in Concrete5
- Choosing what c5 version to develop for
- Use attributes to set background images
- Grant Access Only to Files Users Have Uploaded Themselves
- Converting JSON to an array
- Common Theme Pitfalls
- Overriding Core Files and Extending Core Classes in concrete5.6 and later
- Email user when their account has been activated
- Change Filtered Words in URL Slugs
- Using concrete5 from PHP CLI
- Set Up a Demo Server
- Share dashboard sections between addons
- Using core bootstrap tooltip at your front-end
- Add a mailbox (PM) preview to user profiles
- Hide a newly added page
- Default values in db.xml
- Performance improvements in concrete5 5.6.1
- Let's get Recursive ! [Solving Page Recursion Issues]
- .htaccess snippet
- Show content in more than one place
- Make Responsive Tables
- Creating a Fresh Foundation 4 Theme for concrete5
- Compress JS, and CSS files
- Add dir="rtl" to for a specific subddirectory
- View All products link in e-commerce product list
- Decrease size of your c5 install by removing some unnecessary files
- Restore an internal page type used by the concrete5 core
- concrete5 php debug clips
- Troubleshoot red "1" error upon marketplace package upgrade
- Fix missing 'Upload' button and setting up allowed file types.
- Recovering a lost password without "Forgotten Password"
- Replace Email Body
- Basic SEO
- How to use Bootstrap Tabs in concrete5 dashboard
- Using a SSL proxy with Concrete5
- Faded CSS3 Menu
- Visualise Bootstrap column widths
- Create a split scale slider for greater range.
- .html or .htm file endings for pages
- Basic .htaccess configuration, Setting custom site theme paths , and robots.txt with concrete5
- Main + Sub Navigation with Selected Trail in Multi Language site
- How to hide all child pages under a parent page in autonav
- Change how a block looks : templates
- Avatar Edit information for your user - very basic
- Troubleshooting concrete5 core upgrade: database and core versions
- [French] Afficher une liste aléatoire de pages
- How to create a product page after choosing "Skip Page Creation" eCommerce
- [french] Afficher les résultats de la recherche sur une autre page
- Adding your own 'Page Type' to your theme
- [french] Créer une splash page (page d'entrée)
- Installing Concrete5 on WAMP (Windows) Local Server
- BitNami C5 Stack local to Windows Host Online - Database Table Name Sensitivity - Rename Tables Fix
- Setting Discussion Forums Category Order via Creation Date
- Using ZURB's Foundation Framework 3 with Concrete5
- Add dashboard icons to single pages in concrete5.6
- Set Site Email Default From Address
- Force HTTPS for Entire Website.
- Use query string path parts in a single page
- Superfish IE7 Submenu Gap & Hover Problem Fixes
- Transitioning from Joomla! to concrete5
- Review address on the final step of checkout
- Delete a Project Page
- Modify a packaged theme
- Some tricks for debugging JavaScript
- 10 Useful Tools You Probably Didn't Know Existed, Volume 2
- Page List Active Link
- Using Custom Attribute and Page Type
- Make your own simple custom navigation menu
- Customize PayPal order details to show shipping & sales tax
- Attach jQuery event handlers
- SEO and concrete5
- Manually upgrade concrete5
- Display simple eCommerce cart details
- MySQL database case insensitivity
- Cache ADOdb Active Record Metadata
- Make your layouts responsive with native c5 layout tool.
- How to make Google's mod_pagespeed work with concrete5
- How To Turn Off Sales Tax By User Group in eCommerce
- Create a searchable, extensible page selector attribute
- concrete5 for Drupal Designers and Developers: Page Building Features Compared
- Improve rendering of jQuery plugins
- Concrete 5.5 Editor/Client Tutorials for absolute beginners
- Increase your PHP memory limit
- How to show the blocks of an area in a random order
- How to Convert a Site to concrete5 and Recreate Original Page Paths for Search Engine Recognition/Optmization
- Multi-Site Concrete5 Installation for GoDaddy Shared Hosting
- Protect a jQuery plugin from colliding with files from other add-on packages
- Installing Concrete5 on a MAMP local server
- Translating Site Specific Texts
- concrete5 Add-On Developers: Create Your Own Demo (5.5.0 and Up)
- Create a News system using Composer
- Install concrete5 from the Command Line
- Get marketplace submissions through the PRB
- Generate a .mo file with .po file from mygengo with poEdit
- Page stuck in edit mode?
- External Oracle database connection
- Transfer a project to a new owner
- concrete5 5.5 Content Import Format, Sample Content & Starting Points
- Use the Config table for configuration data
- Use IRC to connect with developers, editors and designers from everywhere
- How to change the Rich-Text-Editor Interface
- Override Site Search Block to Search Through eCommerce Product Titles Only and Return Only Products
- How to Add a Favicon or Apple iPhone Thumbnail in Concrete5.5
- Hide the subdirectory URL
- Restore a login page from the trash
- How to fix a broken uploader on a new installation
- Update Very Old Sites
- Add ability in contact form to reply to the submitter
- 5.5 (and later) User Interface and Twitter Bootstrap
- Getting Help on Forums
- How to display images with RSS displayer
- Absolute Basic Web Stuff
- concrete5 5.5 Stacks vs. Scrapbooks
- Email 'from' field populated using the senders email address
- Setting Up and Using Concrete5's Composer Feature
- Responsive Images – Web Design with Device Optimized Images
- How to add a vanilla forum to your c5 site.
- How to hide tracking code for editable users (post 5.5.x)
- Use tabs in an edit form or dialog
- Download and manually install an add-on
- Creating a single page to handle both Login & Registration
- Make ALL Your YouTube & Other Embedded Videos Auto-Fit
- Add a slider control to an edit menu or form
- Handle Sessions From The DB
- How To Add a Custom @Font-Face to Your Theme
- Customize a core theme
- Validate form inputs in the browser
- Configure additional cache settings via Zend Cache options
- Create a form with a dynamic list of input elements
- Concrete5 and Godaddy shared linux hosting plan - Complete solution
- Making a theme from start to finish
- How concrete5 Events work
- AJAX Lessons
- Sort a list with drag and drop.
- Native Multi-Site Support
- Remove Site Name from your web page header
- Sort an HTML table using jQuery
- concrete5 5.5 White Labelling Support
- Pulling In Sub-pages from Multiple Paths
- Change the format of your site's page titles
- 10 Useful Tools You Probably Didn't Know Existed, Volume 1
- Log user search terms
- Show messages from JavaScript as C5 error messages.
- Facebook's opengraph and concrete 5
- Backup a database
- Special Offers in the Marketplace
- Speed Up Databse Queries with the ADOdb Compiled PHP Extension
- Add a second email field to user registration form
- Change Things Without Hurting Anything : Overrides
- Upgrade - Add another block type or single page to an installed package
- Fix character encoding in your database
- Theming System Single Pages like Login, Register, etc
- Set the Time Zone of your Concrete5 Installation
- Using pretty URLs with hosting on Heart Internet
- Assign a license to a project
- Connecting to an external database other than MySQL
- Concrete 5 Tutorial Vidoes
- Controlling the use of Google Web Fonts through Page Attributes
- Can't Connect to the Community
- How to uninstall add-ons
- [French] Faire du multisite avec Concrete5
- A Mobile Approach in Concrete5
- Transfer an add-on license to a new project
- How to programmatically add comments to a guestbook block
- Manually set up the basic blog (if you didn't include "sample content" when installing your site)
- Running many concrete5 sites
- How to parse the requested path
- Enable Pretty URLs in Windows IIS
- Speed up Concrete5 with Minify and BootstrapCache
- Modifying the default Paging display in Concrete5
- Creating an accordion page
- Install Concrete5 "invisible" over an existing website
- Automatic Email Obfuscation
- Using CloudFlare
- How to Install PageTypes with Custom Attributes assigned By default from a package
- Dynamically concatenate, minify, gzip, and server side cache multiple LESS and CSS files in your theme.
- Security and concrete5
- Disable the cart overlay in eCommerce 2.0.x
- Using a custom callback with the Page Selector
- How to include a tracking code for non-admins only
- Fix block edit error on upgrade from 5.3.3.1 to 5.4.0
- How to move a site from 1 directory on a server to a new directory on the server.
- Add licenses from multiple user accounts to a single project
- How to add the Google +1 button to a site
- Reinstall A Lost Core Block Type
- Project Ownership
- Use Google Web Fonts on your web site
- Get Email Notifications of Site Changes
- Arranging Content
- How to translate a Concrete5's package in your language
- Troubleshoot Mail Problems
- In-context Editing
- Custom Attribute Types
- Clean up copy pasted from MS Word
- Disable the Dashboard Statistics graph (and stats collection)
- Guestbook Closed Comments
- Edit or remove your site name
- A Multi-Site Approach in Concrete5
- How to include files in search results
- Create a Citation Block For Your Site
- Create menu-placeholders in the auto-nav
- How to Make an Easy Dropdown Menu
- Adding the noindex meta tag
- concrete5 and GoDaddy Shared Hosting
- Adding a Jquery Accordion Menu
- Restore a deleted system page (like Login, Members, etc)
- Packaging up a Theme
- Using File Manager Sets
- Use Layouts to Position and Align Content
- File Manager: Tools and Features
- Strategies for Creating Custom Site Themes from an Existing Design
- Add (or change) your site's Favicon
- Use Special eCommerce User Attributes
- Set Up eCommerce and Digital Downloads
- Set Permissions of Specific Areas and Blocks
- Build Out a Site From a Comp
- Using Advanced Permissions
- Monitor Your Site's Traffic
- How to round corners on user's avatars
- How to run certain Jobs via cron
- Backup and Restore File Permissions In Linux
- Explain all these different logins I have!?!
- Using Google Apps for Your Outgoing Mail
- Make Your Site Accessible to Administrators While in Maintenance Mode
- Extend the Rich-Text Editor
- Customizing Superfish
- Migrating from Development to Live Server on Fedora: Step by Step
- Get Pretty URLs working on Dreamhost
- Adding a Facebook Like Box to your concrete5 Website
- Share Content Across Multiple Pages
- Five easy ways to speed a concrete5 Site
- Change Allowed File Upload Types
- Developers Introduction with Derek Allard
- Get the Content Editor's Text and Background Colors to Match Your Theme
- Adding F4V Support to the Basic Video Player Block 2
- Restore the "Generate Sitemap" Job
- Your site's URL
- Disable the Dashboard Statistics Graph
- Reconnect To The Community
- How Can I Edit Page Defaults?
- Setup a subdomain based demo server
- Change Block View Behavior With Templates AKA: Make Anything Fancy
- Setting Up and Maintaining a Centralized concrete5 Installation
- How do I remove the "Powered by concrete5" in my theme's footer?
- Increase Upload Size
- Why do I need view.php in my theme?
- Hardcode a Block into a Page Type
- How do I add a bookmark icon (aka favicon) to my site?
- Running Multiple concrete5 Instances Using a Single Core on a Redhat enviroment
- How do I add Google Analytics tracking code to my site?
- Centralizing Templates/Blocks & Language files
- I can't login!
- Styling the Page List Block
- Stop Themes From Interfering with The edit bar
- How do I exclude a specific page from sitemap.xml? How do I set priority?
- Running Multiple concrete5 Instances Using a Single Core on a Plesk-Managed Web Host
- Mail on Yahoo Hosting
- Create an RSS feed from your site
- File Block: Display File Type Icon next to the Download Link
- Integrate Google site search into concrete5
- Adding Sitemap and File Manager Quick Links to Edit Bar
- SEO Tip: Redirect All Page Paths to One Ending with No Slash
- Converting a site into a theme
- Another Primer on Areas and Page Types
- "concrete-ize" a basic HTML theme in 8 minutes
- Built-In Attribute Reference/Cheat Sheet
- Building an iPhone-Optimized Version of a concrete5 Theme
- Building Sites in Multiple Languages
- Combining Views, Controllers, Events and Models to Create a Example Shopping Cart
- Automatically Expire Pages from a Page List at a Certain Time
- Make a new Custom Attribute Type
- New Cheat Sheet Documentation Launched
- Creating a New Block Type
- Custom Footer Menus using Auto-Nav
- Customize a Block's Appearance
- Creating and Working with db.xml Files
- How-To: Build a Single-Page Powered Editing Interface for concrete5 Pages
- Basic MVC in concrete5
- Primer: Auto-Nav Block
- Hello User Block Example
- JavaScript, jQuery and concrete5
- Custom Block Templates/Views
- concrete5 Add-On Developers: Create Your Own concrete5 Demo (5.4.2.2 and earlier)
- Screencast: How to Create a Client Area
- How to Fix Strict Standards Error
- Hacking core eCommerce for php7 and c5.6.4