SEO urls in rails: .html ending vs. none. What's best? - ruby-on-rails

I'm thinking about a good SEO Url strategy for a blog application. I'm not sure - and maybe it's just the same - but what is better? With or without .html
/blog/entry_permalink_name.hml
VS
/blog/entry_permalink_name
What do you think?

To answer directly you question, without the HTML is better SEO-wise. The search engines take keywords from the url into account. Now the more words or characters there are in the url the weaker the power of a given keyword.
It follows logically that there is no SEO advantage in adding '.html' at the end of the url.
Similarly removing the blog bit would enhance the power of the keywords in the title but if you want to use 'blog' as a valuable keyword, leave it.
Keep in mind that the url is just one of many factors of optimization of a page for SEO, and not the most powerful at that. The common thinking here is that none of these optimization tricks make a substantial difference by themselves but they do cumulatively.

I would suggest removing /blog/ from the url and making it as follows:
/entry-permallink-name
word 'blog' introduces extra irrelevant term to your URL
.html would be mostlikely ignored by search engines, but it's absence makes it a bit more user-friendly, so do dashes instead of underscores.

I disagree about not having the blog entry in there. I don't think 'blog' is an irrelevant term since you are writing a 'blog' application and good has a search 'blog' section.
As for your question, look in your address bar when you view this question. Stack overflow seems like a good site to emulate.
I do agree with xelurg about the dashes instead of underscores.

I would keep the unique id in the name just like stackoverflow. It's a lot simpler that way.

Related

URL Layout for multi-lingual CMS

So I'm trying to add a new, shiny REST webservice to our CMS. It should follow the REST "roules" pretty closely, so it shall use GET/POST/PUT/DELETE and proper, logical URLs. My design is heavily inspired by the Apigee Best Practices.
The CMS manages a tree of categories, where each category can contain a number of articles. For multi-lingual projects, the categories are duplicated for each language (so any article is uniquely identifier by its ID and the language ID). The structure is the same across all languages, only the positions can vary (so category X contains the categories Y and Z in every language, but Y can be before Z in language 1 and the other way around in language 2). Creating a new article or category always also creates copies in all languages. Deleting works the same way, so an article is always deleted in all languages.
FYI: Languages are identified by their numeric ID or their locale (like en_US).
(Please image a leading /v1 in front of all URIs; I've skipped it because it adds nothing to this question.)`
My current approach is having an URL scheme like this:
GET /articles :( returns all articles in all languages
GET /articles/:id-:langid :) returns a single article in a given language
POST /articles :) creates a new article
PUT /articles/:id-:langid :) update a single article in a given language
DELETE /articles/:id :) delete an article in all languages
But...
How to identify languages?
Currently, the locale each language is assigned does not need to be unique, so two languages can in rare cases have the same locale. Using the ID is guaranteed to be unique.
Using the locale (most likely forced to lowercase) would be nice, cause the URLs are more readable. But this would
maybe lead to projects with overlapping locales.
require clients to first fetch the locales (but I guess a client would otherwise have to fetch the language IDs anyway, so that's kind of okay).
I would like to end up with exactly one solution to this and tend towards using the locale. But is it worth risking overlapping locales?
(You can image langid=X to be interchangeable with locale=xx_xx in the following.)
Should the language be a hierarchy element?
In most cases, clients of the API will want to fetch the articles for a given language instead of all. I could solve this by allowing a GET parameter and offer GET /articles?langid=42. But since is such a common usecase, I would like to avoid the optional parameter and make it explicit.
This would lead to GET /articles/:langid, but this introduces the concept that the language is a hierarchy level inside the API. If I'm going to do so, I would like to make it consistent for the other verbs. The new URL layout would look like this:
GET /articles/:langid :) returns all articles in a given language
GET /articles/:langid/:id :) returns a single article in a given language
POST /articles :( creates a new article in all languages
PUT /articles/:langid/:id :) update a single article in a given language
DELETE /articles/:langid/:id :( delete an article in all languages
or
GET /:langid/articles :) returns all articles in a given language
GET /:langid/articles/:id :) returns a single article in a given language
POST /articles :( creates a new article in all languages
PUT /:langid/articles/:id :) update a single article in a given language
DELETE /:langid/articles/:id :( delete an article in all languages
This leads to...
What to do with global actions?
The above layout has the problem that POST and DELETE work on all languages, but the URL suggests that they work only on one language. So I could modify the layout:
GET /articles/:langid :) returns all articles in a given language
GET /articles/:langid/:id :) returns a single article in a given language
POST /articles :) creates a new article in all languages
PUT /articles/:langid/:id :) update a single article in a given language
DELETE /articles/:id :) delete an article in all languages
This makes for a somewhat confusing layout, as the language level is only sometimes present and one needs to know a lot about the system's interna. On the bright side, this matches the system very well and is very similar to the internal workings.
Sacrifices?
So where do I make sacrifies? Should I introduce alias URLs to have nice URL layouts but do maybe unintended stuff in the backgroud?
I had the exact same problem some time ago and I decided to put local in front of everything. While consuming content it makes much more sense to read URLs like:
/en/articles/1/
/en/authors/2/
/gr/articles/1/
/gr/authors/2/
than
/articles/en/1/
/authors/en/2/
/articles/gr/1/
/authors/gr/2/
In order to solve the "no specific locale" issue I would use a keyword referring to all available locales, or a default locale. So:
/global/articles/
or
/all-locales/articles/
or
/all/articles/
to be honest I like global and all because they make sense reading them.
DELETE /global/articles/:id :) delete an article in all languages
hope I helped
My initial approach would have been to have language as an optional prefix in the URL, e.g. /en_us/articles, /en_us/articles/:id, but if you don't want to 'pollute' your URLs with language identifiers you can use the Accept-language header instead, in the same way that content negotiation is defined in RFC 2616. Microsoft's WebAPI is using this approach for format negotiation.

What are the pro/cons if I expose entities keys in url?

I know with symfony2 is very trivial get pretty urls through routing system and I love it. But when the routes parameters are based only in slugs I've got to find by slug.
$em->getRepository('Bundle:Entity')->findOneBySlug($slug);
I thinking about combine both parameters like stackoverflow http://mysite.com/articles/234/the-title. Mantaining the slug parameter only for SEO proposes and find directly with the entity id (234).
$em->getRepository('Bundle:Entity')->find($id);
What are the pro / cons using this strategy. I'm right way?
I would go as you suggested and use both an unique identifier and a slug, because you do not have to worry about unique slugs this way.
But one thing you should is check if the slug is valid.
So do not use URLs like this: /articles/{id}/{unchecked-slug}, because if you do that you can reach the same article with an unlimited number of different/evil URLs, i.e. /articles/123/the-correct-title and /artcle/123/some-dirty-words.
So i would suggest using something like this:
$em->getRepository('Bundle:Entity')->findOneBy(array('slug' => $slug, 'id' => $id);
I am not a SEO expert, but I do not think, that shorter URLs are THAT important, as long as it contains useful words, that may be part of a search.
From a pure SEO perspective, you want to have a shorter URL since they tend to attract more clicks and are easier to share. However, catering to only SEO would be a mistake IMHO.
Adding a unique identifier to the string would be a smart thing to do, and would make things easier to lookup and maintain. I would suggest putting the unique identifier at the end of the URL string to maximize the "SEO effect".
Keywords in the URL might be a ranking signal, but really they drive up the CTR if the keywords found in the URL match the user's query. When that happens, the keywords in the URL become bolded in the Search Results Page (SERP). By putting the ID at the end of the URL, you're helping to ensure that the keywords in the slug have a better chance of appearing to the user, which means a better chance of being bolded, which hopefully leads to more CTR.
Here's what I would suggest:
http://example.com/articles/the-title-234
No one has suggested it so far, so I'll offer what WordPress does. If there is already a permalink in the database that is identical to the one being supplied, you simply concatenate a counter at the end.
http://example.com/blog/my-article
becomes
http://example.com/blog/my-article-2
becomes
http://example.com/blog/my-article-3
The method eywu suggested is second best, but only because you still have the full ID in the permalink. No one wants to remember that, and it has no meaning to search engines.

ColdFusion - What's the best URL naming convention to use?

I am using ColdFusion 9.
I am creating a brand new site that uses three templates. The first template is the home page, where users are prompted to select a brand or a specific model. The second template is where the user can view all of the models of the selected brand. The third template shows all of the specific information on a specific model.
A long time ago... I would make the URLs like this:
.com/Index.cfm // home page
.com/Brands.cfm?BrandID=123 // specific brand page
.com/Models.cfm?ModelID=123 // specific model page
Now, for SEO purposes and for easy reading, I might want my URLs to look like this:
.com/? // home page
.com/?Brand=Worthington
.com/?Model=Worthington&Model=TX193A
Or, I might want my URLs to look like this:
.com/? // home
.com/?Worthington // specific brand
.com/?Worthington/TX193A // specific model
My question is, are there really any SEO benefits or easy reading or security benefits to either naming convention?
Is there a best URL naming convention to use?
Is there a real benefit to having a URL like this?
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
Use URLs that make sense for your users. If you use sensible URLs which humans understand, it'll work with search engines too.
i.e. Don't do SEO, do HO. Human Optimisation. Optimise your pages for the users of your page and in doing so you'll make Google (and others) happy.
Do NOT stuff keywords into URLs unless it helps the people your site is for.
To decide what your URL should look like, you need to understand what the parts of a URL are for.
So, given this URL: http://domain.com/whatever/you/like/here?q=search_terms#page-frament.
It breaks down like this:
http
what protocol is used to deliver the page
:
divides protocol from rest of url
//domain.com
indicates what server to load
/whatever/you/like/here
Between the domain and the ? should indicate which page to load.
?
divides query string from rest of url
q=search_terms
Between the ? and the # can be used for a dynamic search query or setting.
#
divides page fragment from rest of the url
page-frament
Between the # and the end of line indicates which part of the page to focus on.
If your system setup lets you, a system like this is probably the most human friendly:
domain.com
domain.com/Worthington
domain.com/Worthington/TX193A
However, sometimes a unique ID is needed to ensure there is no ambiguity (with SO, there might be multiple questions with the same title, thus why ID is included, whilst the question is included because it's easier for humans that way).
Since all models must belong to a brand, you don't need both ID numbers though, so you can use something like this:
domain.com
domain.com/123/Worthington
domain.com/456/Worthington/TX193A
(where 123 is the brand number, and 456 is the model number)
You only need extra things (like /questions/ or /index.cfm or /brand.cfm or whatever) if you are unable to disambiguate different pages without them.
Remember: this part of the URL identifies the page - it needs to be possible to identify a single page with a single URL - to put it another way, every page should have a unique URL, and every unique URL should be a different page. (Excluding the query string and page fragment parts.)
Again, using the SO example - there are more than just questions here, there are users and tags and so on too. so they couldn't just do stackoverflow.com/7275745/question-title because it's not clearly distinct from stackoverflow.com/651924/evik-james - which they solve by inserting /questions and /users into each of those to make it obvious what each one is.
Ultimately, the best URL system to use depends on what pages your site has and who the people using your site are - you need to consider these and come up with a suitable solution. Simpler URLs are better, but too much simplicity may cause confusion.
Hopefully this all makes sense?
Here is an answer based on what I know about SEO and what we have implemented:
The first thing that get searched and considered is your domain name, and thus picking something related to your domain name is very important
URL with query string has lower priority than the one that doesn't. The reason is that query string is associated with dynamic content that could change over time. The search engine might also deprioritize those with query string fearing that it might be used for SPAM and diluting the result of SEO itself
As for using the URL such as
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
As the search engine looks at both the domain and the path, having the question in the path will help the Search Engine and elevate the question as a more relevant page when someone typing part of the question in the search engine.
I am not an SEO expert, but the company I work for has a dedicated dept to managing the SEO of our site. They much prefer the params to be in the URI, rather than in the query string, and I'm sure they prefer this for a reason (not simply to make the web team's job slightly trickier... all though there could be an element of that ;-)
That said, the bulk of what they concern themselves with is the content within and composition of the page. The domain name and URL are insignificant compared to having good, relevant content in a well defined structure.

What to use for space in REST URI?

What should I use:
/findby/name/{first}_{last}
/findby/name/{first}-{last}
/findby/name/{first};{last}
/findby/name/first/{first}/last/{last}
etc.
The URI represents a Person resource with 1 name, but I need to logically separate the first from the last to identify each. I kind of like the last example because I can do:
/findby/name/first/{first}
/findby/name/last/{last}
/findby/name/first/{first}/last/{last}
You could always just accept spaces :-) (querystring escaped as %20)
But my preference is to just use dashes (-) ... looks nicer in the URL. unless you have a need to be able to essentially query in which case the last example is better as you noted
Why not use + for space?
I am at a loss: dashes, minuses, underscores, %20... why not just use +? This is how spaces are normally encoded in query parameters. Yes, you can use %20 too but why, looks ugly.
I'd do
/personNamed/Joe+Blow
I like using "_" because it is the most similar character to space that keeps the URL readable.
However, the URLs you provided don't seem really RESTful. A URL should represent a resource, but in your case it represents a search query. So I would do something like this:
/people/{first}_{last}
/people/{first}_{last}_(2) - in case there are duplicate names
It this case you have to store the slug ({first}_{last}, {first}_{last}_(2)) for each user record. Another option to prepend the ID, so you don't have to bother with slugs:
/people/{id}-{first}_{last}
And for search you can use non-RESTful URLs:
/people/search?last={last}&first={first}
These would display a list of search results while the URLs above the page for a particular person.
I don't think there is any use of making the search URLs RESTful, users will most likely want to share links to a certain person's page and not search result pages. As for the search engines, avoid having the same content for multiple URLs, and you should even deny indexing of your search result pages in robots.txt
For searching:
/people/search?first={first}&last={last}
/people/search?first=george&last=washington
For resource paths:
/people/{id}-{first}-{last}
/people/35-george-washington
If you are using Ruby on Rails v3 in standard configuration, here's how you can do it.
# set up the /people/{param} piece
# config/routes.rb
My::Application.routes.draw do
resources :people
end
# set up that {param} should be {id}-{first}-{last}
# app/models/person.rb
class Person < ActiveRecord::Base
def to_param
"#{id}-#{to_slug(first_name)}-#{to_slug(last_name)}"
end
end
Note that your suggestion, /findby/name/first/{first}/last/{last}, is not restful. It does not name resources and it does not name them succinctly.
The most sophisticated choice should always and first of all consider two constraints:
As you'll never know how skilled the developer or the device being implemented on is regarding handling of urlencoding, i will always try to limit myself to the table of safe characters, as found in the excellent rant (Please) Stop Using Unsafe Characters in URLs
Also - we want to consider the client consuming the API. Can we have the whole structure easily represented and accessible in the client side programming language? What special characters would this requirement leave us with? I.e. a $ will be fine in javascript variable names and thus directly accessible in the parsed result, but a PHP client will still have to use a more complex (and potentially more confusing) notation $userResult->{'$mostVisited'}->someProperty... that a shot in your own foot! So for those two (and a couple of other programming environments) underscore seems the only valid option.
Otherwise i mostly agree with #yfeldblum`s response - i'd distinct between a search endpoint vs. the actual unique resource lookup. Feels more REST to me, but more importantly, the two have a significant cost difference on your api server - this way you can easier distinct and i.e. charge a higher costs or rate limit the search endpoint - should you ever need it.
To be Pragmatic, as opposed to a "RESTafarian" the mentioned approach /people/35-george-washington could (and should imho) basically respond to just the id, so if you want a named, urlsafe-for-dummies-link, list the reference as /people/35_george_washington. Other ideas could be /people/35/#GeorgeWashington (so breaking tons of RFCs) or /people/35_GeorgeWashington - the API wouldn't care.

Repeating a Parameter in a ASP.NET MVC Route

I am trying to write a route that matches the following URL format:
/category1/category2/S/
where the number of categories is unknown, so there could be 1 category or there could be 10 (1..N).
I cannot use a catch all becuase the categories are not at the end of the URL.
I am actually routing to a web form here (using Phil Haack's example http://haacked.com/archive/2008/03/11/using-routing-with-webforms.aspx), but that is beside the point really.
Any ideas?
To be honest, I found the answer here to be more useful: Using the greedy route parameter in the middle of a route definition
The blog post linked to in the question was extremely useful: http://www.thecodejunkie.com/2008/11/supporting-complex-route-patterns-with.html
I think it's impossible but you could try work around it using this route:
{categories}/S
Then split the categories using the '/' character yourself.
I made a site where I just fixed it to 1-3 categories by registering 3 routes, but I had to work around a lot of things and wasn't really happy with it afterwards.
EDIT: Using S/{*categories} will catch the categories. You can only use it at the end of the URL.
Exactly what you need(ed)
This is a long time lost shot, but I seem to have exactly what you need. I've written a GreedyRoute class that allows greedy segment anywhere in the URL (at the beginning, in the middle or at the end - which is already supported).
You can read all details on my blog as well as getting the code of this particular class.
The main thing is it supports any of these patterns:
{segment}/{segment}/{*segment}
{segment}/{*segment}/{segment}
{*segment}/{segment}/{segment}
It doesn't support multiple greedy segments though (which is of course possible as well but has some restrictions that should be obeyed in that scenario), but I guess that's a rare example where that could be used.

Resources