Today I will show you how to create Grails 3 SEO friendly URL with a simple and effective way without using any plugin. Yes, of course, today you will not find an SEO plugin for Grails 3. But for Grails 2 or less, there is exists.
As default when we call URL, for example, an article it will show like this.
http://www.yourdomain.com/article/show/10
It was because in UrlMappings.groovy of your Grails 3 application it looks like this for calling a single data.
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
Let me break this.
- $controller -> article
- $sction -> show
- $id -> 10
$format is optional use if you want return json or xml as format.
Your requirement is making SEO friendly URL, so it must look like this.
https://www.yourdomain.com/post/10/my-first-article-today
Yes, you might think that URL not clean because it's too long. But don't worry at least we have our title in the last of URL, it is SEO friendly. And here's the step for it.
1. Create new Service
In your Grails interactive console type this command.
create-service com.djamware.FriendlyUrl
This will create a file with name FriendlyUrlService.groovy, replace the content with this.
package com.djamware
import grails.transaction.Transactional
import java.util.regex.Pattern
@Transactional
class FriendlyUrlService {
static transactional = false
/**
* This method transforms the text passed as an argument to a text without spaces,
* html entities, accents, dots and extranges characters (only %,a-z,A-Z,0-9, ,_ and - are allowed).
*
* Borrowed from Wordpress: file wp-includes/formatting.php, function sanitize_title_with_dashes
* http://core.svn.wordpress.org/trunk/wp-includes/formatting.php
*/
def sanitizeWithDashes(text) {
if(!text) return ""
// Preserve escaped octets
text = text.replaceAll('%([a-fA-F0-9][a-fA-F0-9])','---$1---')
text = text.replaceAll('%','')
text = text.replaceAll('---([a-fA-F0-9][a-fA-F0-9])---','%$1')
// Remove accents
text = removeAccents(text)
// To lower case
text = text.toLowerCase()
// Kill entities
text = text.replaceAll('&.+?;','')
// Dots -> ''
text = text.replaceAll('\\.','')
// Remove any character except %a-zA-Z0-9 _-
text = text.replaceAll('[^%a-zA-Z0-9 _-]', '')
// Trim
text = text.trim()
// Spaces -> dashes
text = text.replaceAll('\\s+', '-')
// Dashes -> dash
text = text.replaceAll('-+', '-')
// It must end in a letter or digit, otherwise we strip the last char
if (!text[-1].charAt(0).isLetterOrDigit()) text = text[0..-2]
return text
}
/**
* Converts all accent characters to ASCII characters.
*
* If there are no accent characters, then the string given is just returned.
*
*/
private def removeAccents(text) {
java.text.Normalizer.normalize(text, java.text.Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
}
}
This code will return any String to SEO required string, in this case, replace space or unwanted characters to be "-".
2. Create new TagLib
As above step type this command.
create-taglib com.djamware.Seo
This will create SeoTagLib.groovy file, then you fill this file same as this.
package com.djamware
class SeoTagLib {
static namespace = "seo"
def friendlyUrlService
def convStr = { attr, body ->
out << body() << friendlyUrlService.sanitizeWithDashes(attr.value)
}
}
With this TagLib we can use our service in GSP page.
3. Register new URL in UrlMappings
Open your UrlMappings.groovy in your Controllers folder. Add this lines.
name showPost: "/post/$id/$title" {
controller = "article"
action = "show"
}
Notes: don't use first arguments ("/post") same as controller name, otherwise it will not working at all.
If you are using spring security, just register this "post" to your application.groovy for accessibility.
4. Create link for your article
By default your link for opening an article url is like this.
<g:link controller="article" action="show" id="${article?.id}">${article?.title}</g:link>
Just replace with this.
<g:link mapping="post" params="[id: article.id, title: seo.convStr(value:article.title)]">
${article?.title}
</g:link>
Then try this configuration.
Congratulation, you have SEO friendly URL right now.
Thanks.