SEO Lite – The one calorie SEO addon for ExpressionEngine 2.x

A while back I released DevKit for ExpressionEngine using the module “SEO Lite” as an example. Now this module is ready for download!

Click here to download SEO Lite

Full documentation: SEO Lite documentation

A SEO module for ExpressionEngine – what does it do?

Sure you could add custom fields for this kind of meta data, but SEO Lite makes it cleaner and easier to use for the client.

SEO Lite is a lightweight addon for ExpressionEngine that adds SEO meta data for title, keywords and description for entries on your site, enabling them to rank better in the search engines. It uses a template which you can customize to your needs.

It will add a new tab to the publish entry page called “SEO Lite” where you specify title, keywords, and description for the entry.

If you do not specify anything the original entry title will be used, together with the default values for keywords and description.

Why Lite?

First, it’s very lightweight – you only use one tag to output the template, and this tag uses only one database query to fetch the template, entry title, default entry keywords/description or/and the specific keywords/descriptions for that entry.

So you add the power of SEO optimalization with only one query which should be a good tradeoff and perfect for high-traffic websites.

Second, it’s lite functionality-wise as well. No frills. If you want a more extensive module I recommend NSM Better Meta which is a very good commercial alternative.

The template

The default meta data template looks like this:

<title>{title} - {site_name}</title>
<meta name='keywords' content='{meta_keywords}' />
<meta name='description' content='{meta_description}' />
<!-- generated by seo_lite --!>

This can be edited in the SEO Lite Settings. The only thing that’s replaced by SEO Lite is {title}, {meta_keywords} and {meta_description} and you can use any kind of global variables and EE conditionals in it which should make it pretty powerful.

The Tag

Use this tag in your header template to output the template above:

{exp:seo_lite url_title="{segment_3}"}

The url_title parameter uses {segment_3} to find the entry based on the current url. If you have the entry_id you may also use it like this:

{exp:seo_lite entry_id="{entry_id}"}

Installing the module in a WooTheme

Here’s a video showing how to install the module and use it with any of the WooThemes:

Of course this process will be the almost identical on any site.

ScribeSEO Support In The Works

I’m currently implementing support for ScribeSEO. To get an update when this is ready subscribe to my RSS feed or follow me on Twitter.


Download .zip

Documentation, support, download etc. available over at

Let me know what you think! :-)


Comment by John Faulds on 2010-07-30 12:59:18 +0000

I’ve installed this locally and I can see the meta keywords and description fields in the fields sidebar, but there’s no tab from which to access the fields and enter any information.

Comment by Bjørn Børresen on 2010-07-30 13:36:00 +0000

Hmm, I tested this on 2.1 and after installing I get the SEO Lite tab there automatically .. the module installed fine without any problems? Can you edit the module settings? .. are you logged in as superadmin? Do you have a screenshot?

Comment by Neil on 2010-07-30 18:06:39 +0000

Same error for me – uploaded, installed, no visible tab on an existing channel… Trying to create my own tabs, and dragging and dropping the fields fails too… I am logged in as superadmin, the module works, and the settings loads – i am able to enter template and default desc/key, no other options are present. Thanks,N

Comment by Neil on 2010-07-30 19:12:48 +0000

okay… seems like this error applies…

basically if you completely remove your custom layout and enable everything (i.e. pings, cats, etc) – magically it all works. Looks like a EE bug – annoying! wonder how long for the next build update!

Comment by John Faulds on 2010-07-31 03:54:02 +0000

Yes I can edit the module settings and I am logged in as a superadmin. Screenshot of my publish page is at

Comment by Bjørn Børresen on 2010-08-01 11:51:18 +0000

Thanks for the info Neil, and for following up on this one John! Yup, seems like an EE bug:

I’m not reproducing so can’t confirm it but according to that bug report renaming the tab to a single word should work .. I just did a commit now changing the tab name to “SEO-Lite” instead of “SEO Lite” so you can download over again and see if that helps if you want.

Comment by John Faulds on 2010-08-01 23:31:29 +0000

Hi Bjorn, the new version works (had to delete the custom layout and start again though). Thanks :)

Comment by John Faulds on 2010-08-04 06:38:29 +0000

Actually, I’m still having problems. I thought removing the custom layout and redoing it solved the problem, but it only does while you still have that entry’s page open. If you navigate away and come back to it again, the SEO Lite tab is empty again.

Comment by Bjørn Børresen on 2010-08-04 20:07:46 +0000

hmm, what build are you on John? The latest one released 20th of july (20100720)?

Comment by John Faulds on 2010-08-04 22:15:56 +0000

Yep, that’s it.

Comment by Bjørn Børresen on 2010-08-05 17:36:00 +0000

Ok, so I was able to reproduce your problem now by creating a custom layout. As Neil said, when removing my custom layout SEO Lite appeared again .. so it looks like an EE 2.1 bug :-/

Comment by Bjørn Børresen on 2010-08-05 18:33:29 +0000

Ok, so FYI I got word from EllisLab and it’s fixed for the next release:

Comment by John Faulds on 2010-08-06 04:45:43 +0000

OK cool, good to know.

Comment by Ben on 2010-08-10 05:56:19 +0000

Cool add-on. Any chance you could add options to pass through like title_prefix and title_suffix, similar to LG Better Meta?

Comment by David on 2010-08-12 18:30:28 +0000

Where should the files for the plugin be copied into the site? EE 2.0.1

Comment by Bjørn Børresen on 2010-08-13 14:37:59 +0000

Ben; don’t know if I understood you right but you can pre/postfix the title with whatever in the template.

David; just drop the “seo_lite” folder into /system/expressionengine/third_party/ and you’re good to go (read: install it in the backend)

Comment by Neil on 2010-08-13 17:13:26 +0000

Is this fixed in the latest /2010/08/20 build of EE as it is currently not working for me??? (Still)

Comment by Neil on 2010-08-13 19:56:32 +0000

your language file used the language variable TITLE… This overrides the default one provided by EE and so if i change it in your language file to “SEO Title” it also changes the title on the publish tab!! In min i have changed your language variable to “seotitle” and then changed this in you tab file as well allowing me to change it without affecting the publish page! Cheers, N

Comment by Maleika Esther Attawel on 2010-08-15 21:10:07 +0000

This is great, Bjørn and comes in handy for projects with multiple channels in particular.

Comment by Neil on 2010-08-15 21:43:12 +0000

Sorry to keep sending over bugs. But i am using this on a MSM based site and it fails silently. Stops the template load. So looking at your scripts, i hard coded the site ID into the tag and that causes a: Error Number: 1052 Column ‘entry_id’ in where clause is ambiguous (** Then shows the SQL query – but i didn;t want to cut that over here! **)

I’ll keep digging and notify you if i find anything to solve it.

Comment by Neil on 2010-08-15 22:08:35 +0000

Okay… tracked it back to the MSM being the issue. Without learning how MSM work with modules – yours does not create a new row entry for in the config DB for each site. I only have the original site, and no second site. So when it tries to load the default values it fails as the second site ID is missing. Not sure how to solve it – but i guess you need to hook into getting a new DB row in cofig when a new MSM site is created…

Comment by Danielle on 2010-08-16 10:34:04 +0000

Hi Bjorn, Thanks for this plugin, it’s working well for me aside for one issue. It’s similar to Neil’s above, though I’m not running MSM. If any entry id is passed to the plugin I get the same error:

Error Number: 1052

Column ‘entry_id’ in where clause is ambiguous.

Any suggestions on how to fix it/what might be causing it? Thanks, Danielle

Comment by Bjørn Børresen on 2010-08-17 09:25:11 +0000

Danielle: I just pushed a new version to git which fixes the entry_id bug. Thanks for reporting it!

Niel: don’t apologise for sending bug reports, I appreciate someone testing it and letting me know when they find something wrong :-) .. I’ll set up some better environment for bug reports etc than this place, but until then comments work. Anyway, my latest commit should fix the entry_id problem. I also updated the use of ‘title’ in the language file. And I’ve implemented an experimental thing for MSN – I haven’t tested it myself but in theory it should work like this: when you create a new site you need to go into the SEO Lite config and hit save once more to save the config for that site. This way you can have different templates etc. per site. Should work, but still untested from my side..

Comment by Bjørn Børresen on 2010-08-17 09:25:56 +0000

The latest version can be downloaded from github as usual:

Comment by Steve James on 2010-08-24 01:20:05 +0000

When I uninstall your Module, it removes EE 2.0’s default title fields from all my PUBLISH pages! Do you have a work-around for this?

Comment by Bjørn Børresen on 2010-08-25 07:32:17 +0000

Hi Steve, that seems very strange .. if you could give me login details for your backend so I can have a look around and see what the problem might be that’d be appreciated (send me an email at “mail @ this domain”) ..

Comment by Moonbeetle on 2010-09-08 11:55:07 +0000

This is a very fine Add-on. Thank you Bjørn!

A suggestion, I don’t know how hard it is to program, would be to add a conditional check in the parsing of the {exp:seo_lite url_title=”{segment_x}”} so that if no entry can be found with url_title == {segment_x}, the passed value {segment_x} is used as a title anyway. At this moment, if {segment_x} doesn’t relate to any url_title, nothing gets outputted.

Comment by Lincolnpixel on 2010-09-08 23:03:24 +0000

Hi, Thank you Bjørn for this fantastic module.

@Moonbeetle i managed to do what you are trying to achieve with this

{if segment_2 OR segment_1 != ”} {exp:seo_lite default_title=”{segment_1} | {segment_2}” url_title=”{segment_2}”} {/if}

Bjørn , your opinion?

Comment by Bjørn Børresen on 2010-09-09 06:53:09 +0000

Thanks guys,

Lincolnpixel – yepp that works, if it finds an entry it will use the entry title, if it doesn’t it will use what you specified there. Actually that {if} isn’t necessary (unless you need it to know what to give to default_title of course)

Moonbeetle – the solution above should have you covered .. I’m not sure what the best solution is here – I can see situations where people would just want the {site_name} to show if no entry was found (which is specified in the template, so SEO Lite should add nothing) .. anyway using default_title is the right approach for now.

Comment by Lincolnpixel on 2010-09-10 11:37:57 +0000

hi, just updated to the latest version with the “default_title_prefix” i’m getting this error

A PHP Error was encountered

Severity: Warning

Message: htmlspecialchars() expects parameter 1 to be string, object given

Filename: helpers/form_helper.php

Line Number: 639

any help?

Comment by Bjørn Børresen on 2010-09-10 12:17:08 +0000

gah .. yeah I forgot the update() function so you’ll have to do a uninstall/install.

Comment by Bjørn Børresen on 2010-09-10 12:21:56 +0000

… or wait till I have fixed the update() function ;) .. you’re too quick! :-P

Comment by Bjørn Børresen on 2010-09-10 12:51:35 +0000

Ok, if you download the latest version now update from 1.1 to 1.2 should work painlessly.

Comment by Lincolnpixel on 2010-09-10 14:09:55 +0000

Sorry for been to fast The new version fixed it! Thanks

Comment by Bjørn Børresen on 2010-09-10 14:11:28 +0000

haha .. thanks for confirming the fix :-)

Comment by Moonbeetle on 2010-09-13 16:58:45 +0000

Bummer. SEO Lite and Structure don’t mix. Channels that are managed by Structure don’t display the SEO Lite tab in the publishing form.

Comment by Bjørn Børresen on 2010-09-13 17:10:05 +0000

Hmm, I don’t see a reason why that should be the case. SEO Lite will just add a tab like any other third party addon .. is this a Structure issue?

Comment by Moonbeetle on 2010-09-13 17:41:10 +0000

It’s most likely an upgrade problem of either Structure or ExpressionEngine. I noticed that when I add a new channel and set it to be managed by Structure I can get both the Structure and the SEO Lite tab in the publish entry form. While for a channel that already contained data that was entered prior to upgrading Structure to the latest version it seems impossible to have the SEO Lite tab added.

Comment by Bjørn Børresen on 2010-09-13 18:02:18 +0000

Ok. It would be great if you could update me if you get any more info on this. If it turns out to be a SEO Lite problem I’d like to fix it, but yeah it does sound like a Structure/EE problem just from the info we have so far so I’ll just leave it at that for now.

Comment by Moonbeetle on 2010-09-13 23:56:24 +0000

Found it! Apparantly some publish Toolbar layout was saved for the channel that was managed by Structure prior to having installed SEO Lite. My guess is that if EE finds a saved Toolbar layout for a channel, it will use this saved layout (obviously), but also neglects to list any new tabs for modules that have been installed AFTER the toolbar layout was changed.

Comment by Steve Hurst on 2010-09-24 01:21:35 +0000

I’m running this on an MSM set up, and every time I update the config settings for a site, it overwrites the other site’s settings. I checked SQL manager, and it has a different row for each site created, with the correct site id, but each time I update the settings from any site’s SEO Lite config screen, I overwrite the rest.

Comment by Bjørn Børresen on 2010-09-27 09:52:23 +0000

Thanks for the report Steve, this is now fixed in the latest version on github.

Comment by Moonbeetle on 2010-10-08 12:45:19 +0000

In the config: {title} – {site_name}

In the template: {exp:seo_lite default_title=”Test page”}

This should output: Test page – [Name of the site]

For some reason I always get: – [Name of the site]

Comment by Moonbeetle on 2010-10-08 13:21:36 +0000

Got it! Somehow I had double slanted quotes instead of double straight quotes in there.

Comment by Bjørn Børresen on 2010-10-08 13:23:36 +0000

Cool :-) .. removing from todo ;-)

Comment by Jesse on 2010-10-08 17:10:35 +0000

Hey Bjorn – thanks for this great module! It’s very helpful.

I’ve got a question on one thing though – In the following URL – the module isn’t picking up on the entry id at the end of the uri. I’ve tried both the {exp:seo_lite use_last_segment=”yes”} as well as the {exp:seo_lite entry_id=”{entry_id}”} and neither one of them pick up the entry.

Any ideas? Thanks :-)

Comment by Bjørn Børresen on 2010-10-11 11:34:00 +0000

Hmm, I see why use_last_segment doesn’t work cause it’s expecting the URL title, not the entry_id. Not sure what the best fix is there, maybe another parameter called use_last_segment_id or something. Don’t think I want to do magic there to find out whether or not it’s an url_title or entry_id.

About using entry_id=”{entry_id}” that should work. I don’t know how your setup is but might it be that {entry_id} gets parsed after the seo_lite module so that what seo_lite gets is {entry_id} instead of 59?

Anyway, a fix might simply be to use entry_id=”{segment_3}”

Comment by noklew on 2010-10-23 19:22:24 +0000

3 custom fields placed under the new tab is the same as this in a client eyes. So I have to ask…why bother?

Comment by Bjørn Børresen on 2010-10-24 14:49:08 +0000

Nokolew; what if you have several channels? And you’d probably like to use the same header emebed/snippet on all pages, right? It also saves you a channel:entries tag to populate the title tag etc. I think this approach is better / easier than creating custom fields. it might not make much of a difference for the client, but it does make it easier for you.

Comment by Ross on 2010-10-28 14:52:42 +0000

Hey, great plugin!! Thanks!

I am trying to get the title bar to display something like this – Products | Introduction – Pulling the TITLE of the post into the titlebar and not the segment like it currently does. Any suggestions?

I tried this with no luck… {exp:seo_lite url_title=”{segment_1}|{segment_2}|{segment_3}”}

Comment by Jean St-Amand on 2010-10-28 17:59:09 +0000

Hi Bjorn: can more than {title} – {site_name} be used to populate the tag? I’d like to be able to pull a section heading in as well. So something like:

{title} | {section_name} | {site_name}

I tried using the default_title to do this, but then the SEO lite title gets overridden and the entry title is used instead (assuming I pass that as an embedded variable) Is there a way to pass a variable into the title?

Comment by Bjørn Børresen on 2010-10-28 18:24:13 +0000


The _urltitle parameter is used to fetch the entry, either that or the _entryid parameter. I think what you’re trying to achive is best done in the template (do it in the SEO Lite Control Panel .. just change the template there to {title} | {segment_2} | {site_name} or whatever ..)

Jean St-Amand:

{section_name} can be used if it is available to the template parser at that point. It is not fetched from the entry (only title / keywords / description is). But getting custom field is a nice additional feature request I guess .. is that what you’re trying to do or is {section_name} populated from somewhere else?

Comment by Lincoln on 2010-11-06 08:59:38 +0000

Hi, i’m on 2.11 Build:20101020 still affected by the publish tab layout problem, the SEO Lite Tab is not visible. (tried the patch already). help pls.

Comment by Ian on 2010-11-08 04:49:21 +0000

Hi Bjorn,

Is SEO Lite {segment} aware? I have tried to implement your answer to ross in SEO Lite’s template but I just get:

My Page Title | {segement_2} | My Site Name

(both page title and site name are working fine. I am currently using the {exp:seo_lite use_last_segment=”yes”} )

Thanks for the great work!


Comment by Bjørn Børresen on 2010-11-08 08:53:20 +0000

Iain, it’s {segment_2} not {segement_2} ;-)

Lincoln: that’s strange, the bug is marked “Fixed for next release” .. which means it should be out now. I will have a look at it.

Comment by Lincoln on 2010-11-09 09:30:59 +0000

ok, thanks

Comment by Dmitry Romanovsky on 2010-11-11 12:55:15 +0000

Hi Bjorn,

just installed ‘SEO lite’ module, it works fine in the template but it doesn’t create a new tab to the publish entry page. Any ideas why?

respect, dmitry

Comment by Dmitry Romanovsky on 2010-11-11 13:10:03 +0000

sorry, i just realised: it dosn’t create the ‘SEo lite’ tab only on the publish entry pages with custom layout.. any solution to it? Or.. how do i remove custom layout and restore the default one (for the sake of ‘SEO lite’ tab)?

Comment by Doug Biggerstaff on 2010-11-11 22:16:33 +0000

Hi Bjorn, I’m having issues with SEO Lite not posting channel specific content to pages.

All that is displaying on the page are the default values in the “Welcome to SEO Lite” setup.

I’ve used the tag examples in the instructions to no avail.

EE 2.1.0 – Build: 20100810

Any thoughts?

Thanks very much, Doug

Comment by Bjørn Børresen on 2010-11-15 13:55:50 +0000

Re: custom publish layout

If you have custom layout it will not create the SEO Lite tab automatically.

To do this manually go to the publish screen and select “Show toolbar”. Click “Add Tab” and give the tab a name (ie. SEO Lite) .. and then drag the “SEO Title”, “SEO Meta Keywords” and “SEO Meta Description” into the new tab before saving your new layout to a member group as usual.

I have prefixed “Title”, “Meta Keywords” and “Meta Description” with “SEO” to make it easier for people who use custom layouts. To get this update download the latest release from github.

Comment by Bjørn Børresen on 2010-11-15 14:02:22 +0000

Doug Biggerstaff: I’ll look into the pages problem you’re describing.

Comment by Doug Biggerstaff on 2010-11-16 22:16:21 +0000

Thanks Bjørn, but to be clear, I’m not referring to “pages” as an entry from the Pages module, but simply a site page – any page.

Sorry for any confusion.

Thanks, Doug

Comment by Steve on 2010-11-17 18:39:18 +0000

SEO Lite works great except for my home page which is

What do I need to do so that SEO Lite sees that? Right now it’s only returning the defaults.

I am using {exp:seo_lite use_last_segment=”yes”} and I am new to EE.

Thanks, Steve

Comment by Bjørn Børresen on 2010-11-17 18:59:02 +0000

Steve – the homepage sounds like the perfect location for the defaults if you ask me :-) .. but if you’re displaying dynamic information on the homepage (ie. from a channel) you can specify the entry_id parameter if you wish.

Comment by Steve on 2010-11-17 21:03:23 +0000

That makes perfect sense (the defaults)!

But I am using displaying dynamic information on the homepage, but when I use {exp:seo_lite entry_id=”{entry_id}”} all I get are the defaults on every page.

The embedded header comes before my {exp:channel:entries} so may that’s why?

{embed=”embeds/html_header” page_title=”Teachers for Home Instruction and Special Education”}

<div id="sidebar1">



<!-- end #sidebar1 -->

<div id="mainContent">

    {exp:channel:entries channel="home" disable="categories|member_data|pagination" sort="asc" }




Thanks, Steve

Comment by Bjørn Børresen on 2010-11-17 21:26:04 +0000

Yepp, that’s why .. if you want to give entry_id to seo_lite in that example you’ll have to have the embed inside the channel:entries tag and then use {embed:entry_id} in the html_header template to make sure seo_lite gets that entry.


Since support in these comments are getting a bit difficult to follow please post support requests in the SEOLite forums over at devot-ee:

btw – you can also vote SEO Lite for “Module of the year” on devot-ee: :)

closing comments