Automatically add auto-generated short URLs to your sNews CMS

Automatically add auto-generated short URLs to your sNews CMS

This is my first sNews CMS mod/hack to be made public in quite some time, I hope someone finds it useful. This modification will add rel="shortlink" & rel="shorturl" tags to the head of your published items.

What do I mean by published items? Basically all your articles & "pages", not the default category/home page views or hard-coded sNews pages (contact, sitemap, etc). We don't really need/want shortlinks to ever-changing pages (home, category views, etc) anyways.

Why?

Unless you've been living under a rock, you've no doubt used or at least heard of Twitter, and the 140 character limitation for Twitter entries. So when posting URLs, people have relied on URL shortening services, such as bit.ly to reduce the long SEO-Friendly URLs into as few characters as possible. With this mod you can skip using bit.ly or others services for publishing shortlinks on your own site, for any published items (articles/pages). Another big plus about using these short urls is they never change, as they are based on the unique article IDs from the database. Helps prevent linkrot and eases redirect management.

Adding the code

We will be editing 2 pages for this one, index.php & snews.php. So make a back-up of these files now & let's get started. Now open snews.php and add this function to the very bottom of the file, just above the closing PHP tag;

function redirectShortUrl() {
    $url = trim($_GET['category'],"/"); // fetch & trim the category
    if (ctype_digit($url) && strlen($url) < '7') { // url is a short number, let's process it
        $url = clean($url);
        $query = 'SELECT a.id AS aid,a.seftitle AS asef, c.seftitle AS subsef,x.seftitle AS csef
                FROM  '._PRE.'articles'.' AS a
                LEFT OUTER JOIN '._PRE.'categories'.' as c
                    ON category = c.id
                LEFT OUTER JOIN '._PRE.'categories'.' as x
                    ON c.subcat = x.id AND x.published =\'YES\'
                WHERE a.published = \'1\' AND a.visible = \'YES\' AND a.id ='.$url;
                       
        $result = mysql_query($query); 
        $num_rows = mysql_num_rows($result);
        $row = mysql_fetch_row($result);
        if ($num_rows == '0') {
            $error = true;
        } else {
            if (empty($row[2]) && empty($row[3])) { // found a matching page
                $goto = '/'.$row[1];
            } elseif (!empty($row[2]) && empty($row[3])) { // found a matching article w/cat
                $goto = '/'.$row[2].'/'.$row[1];
            } elseif (!empty($row[2]) && !empty($row[3])) { // found a matching article w/cat & subcat 
                $goto = '/'.$row[3].'/'.$row[2].'/'.$row[1];
            }      
        }
        if ($error != true) {
            header ('HTTP/1.1 301 Moved Permanently');
            header ('Location: '.$goto.'');
            exit;
        }
    } // not a number, pass to snews as-is
}

That function will sniff out the shortlinks and check for them in the database, perform the redirect if necessary, or simply pass the url on sNews. Now within the function title(), and the following code below the meta keywords output;

// BEGIN SHORTLINK 
$query = 'SELECT id FROM '._PRE.'articles WHERE title = \''.$_TITLE.'\'';
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
if ($numrows == '1') {
    $row = mysql_fetch_row($result);
    echo '<link rel="shortlink" type="text/html" href="'._SITE.$row[0].'" />
    <link rel="shorturl" type="text/html" href="'._SITE.$row[0].'" />';
}
// END SHORTLINK

That little bit of code checks for a matching title and inserts the shortlinks if there is a match. Now lastly, open index.php, and add the redirectShortUrl fucntion just below the snews.php include;

include('snews.php');
redirectShortUrl();

That's it! Now upload your modified files and you should see the shortlinks on your articles & pages now. Clicking a valid shortlink should redirect you to the SEO Friendly URL on your site.

Extending

So now you've got short URLs for your pages & articles... what do you do with them? Well obviously you can post the shortlinks by hand in your Twitter/SMS/Facebook posts, but I've also created a simple script that will generate a shortlink for 3rd party services. I use TwitterFeed to automatically post all my articles to Twitter. How? Simply sign-up, add your rss-articles feed to TwitterFeed & link your account to Twitter. Now, to use your own sNews site for short URLs, we have to do a little magic, OK, not magic, we have to convert the URL back to a shortlink for TwitterFeed.

This is how we will do this. Download shortenurl.txt, save it as shortenurl.php, edit the database variables and upload to your server. Now, after you have linked your Twitter, Facebook, etc. accounts to TwitterFeed, go to the TwitterFeed dashboard and do the following;

  1. click the edit button to edit your feed.
  2. click the "Advanced Settings" option.
  3. on the "Shorten link through" dropdown, select "custom"
  4. in the "Custom endpoint" box, type "http://site.com/shortenurl.php?url=%@"

Obviously change site.com above to whatever your domain is. Now whenever you post a new article to your RSS feed, TwitterFeed will pick it up, post it to Twitter and use your own short URL as the linkback.

Caveats & Gotchas

There are 2 major considerations that might cause problems for users;

  1. This script uses the unique IDs from the articles table in the database to generate the shortlinks. This works well, I have allowed up to 6 digits in the code, so unless you've created 1 million articles/pages, you should be fine. However, if you started the MySQL auto-increment at a large number, this could be a problem, but there are work-arounds for that.
  2. Because this script uses the unique table IDs, if you have an article or page with a name of just digits, under 1 million (ex. mysite.com/24312), it will conflict. Do not use this script as it is, or consider adding a letter to your article/page names.

Wrap up

Well, if all goes according to plan (this is my first real post using this new shortlink system), then I should see this article posted to twitter soon, with a linkback containing my domains shortlink. As always, any questions or comments, feel free to leave a comment.

Tags

 

You might like

Comments


Glad to see you're still alive. :) Nice mod, I might add it when I finish messing with the rest of my site.


Hi Matt,
glad to see ya back.
That Mod is a great idea but,
your guinea pig couldn't make it work (as usual.
Is there a syntax error there :
$query = 'SELECT id FROM '._PRE.'articles WHERE title = ''.$_TITLE.''';

Or did I make a typo somewhere?


Hi Phillipe! You're correct, the slashes [\] were being stripped in the article, I have converted them to HTML entities and now they show.

Both queries need them;

$query = 'SELECT a.id AS aid,a.seftitle AS asef, c.seftitle AS subsef,x.seftitle AS csef
                FROM  '._PRE.'articles'.' AS a
                LEFT OUTER JOIN '._PRE.'categories'.' as c
                    ON category = c.id
                LEFT OUTER JOIN '._PRE.'categories'.' as x
                    ON c.subcat = x.id AND x.published =\'YES\'
                WHERE a.published = \'1\' AND a.visible = \'YES\' AND a.id ='.$url;

$query = 'SELECT id FROM '._PRE.'articles WHERE title = \''.$_TITLE.'\'';


Good.
Now, what is this "function count_mysql_query()" you got? Is it a PHP built-in function?


Oh, yeah, sorry, that's just a wrapper function for mysql_query, you can drop the "count_"... I use that to test the total queries on a page.


Ah?
Okey...
I'm gonna test it tomorrow "on air".
See you.


Haha, thanks for helping work out the kinks as usual!

BTW, if you want the function, add this to your snews.php;

function count_mysql_query($sql) {
    global $query_count;
    $query_count++;
    return mysql_query($sql);
}


Then do a find & replace all the mysql_query calls with count_mysql_query, that will count them all.

Lastly, add this to the bottom of your index.php file;

<?php echo "<!-- ".$query_count." queries -->"; ?>

Add then it will show you how many queries you've used within the current page.


Ah! Superb Matt! Thanks a lot.
Just a little question:
why do you place those 2 "link rel=" in the head?


1st step works real fine on line.
I use it for the permalink:
See http://normandie-web.hiseo.fr/36 (right col)...

I'll try the twitter service one day.
Thanks a lot Matt.

What else about sNews do you have under your hat?


I don't really have anything planned at the moment, maybe an update to the polls mod, to allow for closing polls from within the admin panel maybe.

I've looked at a few ideas people have had, but I'm so busy at work these days I really don't have much time to devote to hacking around.


Yo Matt,

I have a problem with this. Where must I see those links? I've done whats written. But its really wierd :)
Nothing happens!

Cheers
Dai


Hi David,

The links should be in the head of the HTML document you're viewing, on "pages" & "articles"

--Matt


Ok, nothing happens. Can you take a look if i copied it wrong.

//TITLE
function title() {
	global $categorySEF, $_DESCR, $_KEYW, $_TITLE, $_NAME, $_XNAME;
   	echo '';
   	$title =  $_TITLE ? $_TITLE.' - ' : '';
   	$title .= $_NAME ? $_NAME.' - ' : '';
   	$title .= $_XNAME ? $_XNAME.' - ' : '';
   	if (check_category($categorySEF) == true && $categorySEF != 'administration' && $categorySEF)
   		$title .= l($categorySEF).' - ';
   		$title .= s('website_title'); 
		echo '
			'.$title.'
			
			
			';
			// BEGIN SHORTLINK 
$query = 'SELECT id FROM '._PRE.'articles WHERE title = ''.$_TITLE.''';
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
if ($numrows == '1') {
    $row = mysql_fetch_row($result);
    echo '
    ';
}
// END SHORTLINK
	if (_ADMIN) {
		echo '';
			include('js/admin.js');
		echo '';
	}
}


Thanks Matt!


David, it doesn't appear that you're echo'ing the shortlink codes.

if ($numrows == '1') {
    $row = mysql_fetch_row($result);
    echo '<link rel="shortlink" type="text/html" href="'._SITE.$row[0].'" />
    <link rel="shorturl" type="text/html" href="'._SITE.$row[0].'" />';
}


I really dont get it. Where must I put this code :(
Nothing happes and Ive copied the code below:

';


It should go in the function title(), I'm not sure why it's not working for you.


Yo Matt,

found something out. When I'm on the correct post.
For example: http://www.ryuu-dev.net/uncategorized/testek

And when I click CTRL+U I see the shorturl...but why its not displayed under the Title of the post?

Or this script works like this? If it works like this, how would I echo the url below the title of the post?

I thinks something here must be changed:

echo '
';

But dunno what =)

Cheers,
Dai


Hi David,

That's the way it's supposed to work. The shortcut url isn't currently echo'd under the title of the post.

I'll have a look at what can be done to make that happen & repost here later.


David, if you want to add the permalink under the title of the article, try this;

echo 'Permalink: <a href="'._SITE.$r['aid'].'" />'._SITE.$r['aid'].'</a>';

Place that under the post title in the articles() function. I've added it at the bottom of my articles.


Sweet! Especially with the permalink addition.

Oh, if you have time on your hands and feel up to it, maybe you could suggest a solution to my question here: http://snewscms.com/forum/index.php?topic=...
I'm planning on working it into a couple of new themes but I'm a bit stuck (to no-one's surprise ... :D)

Cheers


Matt, I came across an issue when testing locally. Basically when clicking the permalink, which had the structure "localhost/site/category/article", the shortURL redirect threw me to "localhost/category/article" which equals 404. So I looked and looked and ... looked some more, and finally came to the conclusion that the $goto construction needs revising. I don't know if it's to do with the site position in the server tree or not, but the following is what worked for me:
function redirectShortUrl()
if (empty($row[2]) && empty($row[3])) { // found a matching page
        $goto = $row[1].'/';
    } elseif (!empty($row[2]) && empty($row[3])) { // found a matching article w/cat
        $goto = $row[2].'/'.$row[1].'/';
    } elseif (!empty($row[2]) && !empty($row[3])) { // found a matching article w/cat & subcat
        $goto = $row[3].'/'.$row[2].'/'.$row[1].'/';
    }     
}
if ($error != true) {
    header ('HTTP/1.1 301 Moved Permanently');
    header ('Location: '._SITE.$goto);
    exit;

In other words, I had to remove the slash preceding $goto for each $row[] as well as adding ._SITE. to the header('Location...') line. This makes the redirect work. Note though that this test was only done locally, I haven't added the TwitterFeed bits yet.
Makes sense?


Thanks for the feedback Fred, I'm crazy busy at the moment, so I will leave your suggested fix up here in case it can benefit someone else until I have the time to take a look at it myself.


Hi snoozers,
Yes! Fred is right. His fix makes the job locally and online.
Kudos.


Comments are closed. No new comments allowed.

Copyleft 2002 - 2017 Matt Jones
Hand crafted with HTML5 & CSS3
↑ Back to top