I've been struggling with static content and wanted some other opinions on how to best approach it.

Currently, I have a channel called Static Content where I, obviously, post all the "static" content for the site. In the past, I've created a template for each page. I'm trying to make my templates more DRY, so I'd like to avoid that if possible. Most of the sections/pages are similar, but there are slight differences, so I'd like to have a template group for each main section.

My original idea was to create a template group for each section and then use some embeds to determine some of the unique section content. Basically something along these lines:

"about" template group index:

{header} {!--snippet --}
    {embed="embed/.sidebar" current="about" show_ad="y"} 
{footer} {!--snippet--}

.static-content embed:

{exp:channel:entries channel="static_content" url_title="{last_segment}" limit="1" require_entry="yes" dynamic="no" disable="categories|category_fields|member_data|pagination"}
    {if no_results}{redirect="404"}{/if}


This works really well except for the obvious. I can technically go to http://mysite.com/products/history and pull up the content that should really only appear at http://mysite.com/about/history. How do people usually avoid this problem? Categories? Add-Ons? Pages module? Different channels for each section (I hope not)?

Any suggestions would be appreciated.

2 Answers 2


It sounds to me like you need the Pages Module. Essentially you'll create a single template, more if you need to, and then each entry you create using a channel assigned to the pages module, in your case "static", can have a unique url. So you'll easily be able to assign domain.com/foo or domain.com/bar

I use pages regularly for this. IMO it's really great for a limited number of unique pages.

The alternative to this is using Structure which is a very popular commercial addon for EE that allows you to do this easily for all pages/entries on your site.

  • 2
    If you head down the Pages Module route you should definitely take a look at Better Pages, which is basically Pages on steroids. Apr 24, 2013 at 2:45
  • Agreed, better pages is super sweet.
    – CreateSean
    Apr 24, 2013 at 13:18
  • Thank you both so much! I hadn't heard of Better Pages before, but I will be sure to check it out. I briefly tried the Pages module earlier, but from what I could tell it didn't seem to prevent the duplicate URL issue. I could just be coding my templates incorrectly, though.
    – gaarmaster
    Apr 24, 2013 at 14:59

I tend to handle what you're describing with a separate channel for each major section - not that this is absolutely necessary mind you, but I do find it helps with the logic in template. When I combine it with stash add-on, it works wonders. Then, my template group index template has little other than the logic of what to show when that template is hit and passes the result of that logic into a wrapper template. It gives me a very high degree of control, while maintaining a very consistent experience for the site editor with everything being in channel entries accessible through the publish/edit screens. So for example, a "static" about section, as you describe would be handled like this, the way I've handled it:

1) Create a channel field group for static pages called "pages" (you could make this channel specific if you wish to allow for more separation of field approach between channels - sometimes I do, sometimes I don't)
2) Add custom fields to the field group, such as cf_pages_body (and any other fields you might need, such as seo fields, alt titles, etc)
3) Create a channel for static pages called "about" and assign it the pages field group and your default status group
4) Create a template group called "about"
5) Create a template group called "layouts"
6) In the layouts template group, create a wrapper template called ".inside" that contains all the wrapping html for the inside page - you can of course break that up further with snippets for a DRY approach to the template code itself
7) In the "about" group index template, you lay out your logic use stash:set to stash the results to parse into your ".inside" wrapper template
8) In the .inside wrapper template, you use stash:get to grab the stashed values associated with the accessed URL

So a very simplified version (stash has a lot of additional parameters you could use for performance, parsing priority, etc. that I'm not showing at all here) of the your logic template may be:

{exp:channel:entries channel="about" orderby="date" sort="desc" dynamic="yes" disable="whatever|you|can|disable" limit="1"}
{if no_results}{redirect="404"}{/if}
{exp:stash:set_list name="page_body"}

In this example, I'm using stash:set_list tag pair to stash each custom field in a "list" in which each stashed element receives a name that is then called upon in the wrapper template to "get" and parse in place. For a simple example, this will do. It allows you to be a bit more DRY this way since you can avoid putting any formatting markup in there and instead handle that in the wrapper template.

Then in the inside template, you would get that stashed entry content (again, simplified):

{exp:stash:get_list name="page_body"}
<title>{entry_title} | {site_name}</title>

When static content pages like this are handled as entries, you may also find value in using an add-on for entry ordering with this approach as well so there is a simple way to choose the order of static page entries. It would make more sense than ordering based on date or a custom ordering field in the field group that you can't see in the edit list view. Low Reorder is a good choice for this.

Important to note - naming conventions become a lot more important the more DRY you try to get - something to consider in order to plan an approach like this.

Hoping I haven't overlooked something in the example - going from memory to keep the concept a bit simpler than my actual implementation, so I'll correct if an issue is caught that I've missed. Hopefully this helps.

  • Wow, Jean! Thank you so much for your thorough and thoughtful answer. The helpfulness of the EE community never ceases to amaze me! I've glanced at Stash a few times but always got confused/intimidated on how I'd use it. This is the first time I've had an "aha" moment. Can't wait to try this out on future sites!
    – gaarmaster
    Apr 24, 2013 at 15:02
  • Aha moments are what we all strive for. Stash brilliantly cheats (or takes advantage of) parse order to permit you to save entry content just long enough to inject it into the wrapper template - at least that's how I've come to think of it, rightly or wrongly. For a lot more intelligent discussion on stash than I can offer, be sure to lookup some of the fabulous articles on the subject of template partials with stash that are linked from the bottom of the stash page on devot-ee.com Apr 24, 2013 at 15:16
  • You could also use Jean's method with say, KREA's Content Elements: devot-ee.com/add-ons/content-elements I've been finding it a bit of a godsend for irregular static content, as well as doing HTML user guides for clients. Apr 24, 2013 at 15:46
  • That's a great idea, nonprofit_tech! I had purchased Content Elements late last year but haven't had a chance to work with it. Due to deadlines, I probably can't implement it this time around, but I will definitely give it a go next time.
    – gaarmaster
    Apr 24, 2013 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.