17 - Implementing the Latest News Sidebar Widget, a Contact Form, and the Search Engine
In this chapter we’ll round out the rest of the site by implementing the sidebar latest news, the contact form and the search engine.
Sidebar Latest News
This really should have been part of the Weblog implementation in Chapter 15, but that chapter was long enough already and it just didn’t fit in.
The goal with this sidebar widget is to do two things:
- Allow a client to update several pages or sections of the site by the publishing of one post. This is one of the great advantages and “sells” of a system like EE - the finished site can not only be updated by an end client but the process is simple and updates are leveraged through reuse across the site.
- Give greater prominence to the most updated/freshest part of the site. From a user perspective you are helping them easily find the latest and greatest content by bubbling it to the Home page and every other section of the site.
Implementation here is pretty straight-forward. You’ll need to edit your existing placeholder embeds/latest_news template to add the code I’ll give you. You’ll need to tweak the paths and category parameters and then save the updated template.
Tweak the Template
Let’s look at the code here as we’re doing something a bit new:
<h3>Latest news</h3>
<div class="lcontent">
{exp:weblog:entries weblog="weblog" dynamic="off" limit="1" category="7" disable="pagination|trackbacks|member_data"}
<p>
<strong>{entry_date format='%m/%d'%y'} : {title} </strong>
{exp:word_limit total="30"}{exp:html_strip}{body}{/exp:html_strip}{/exp:word_limit}
<a href="{url_title_path=weblog/comments }">more >></a>
</p>
{/exp:weblog:entries}
</div>
Overall this is a pretty straightforward use of the workhorse exp:weblog:entries tag. Note the dynamic=“off” parameter again used so that EE will ignore the current URL when building the results for this tag.
The important parameter here is the “category=7”. This limits the results of this tag to just entries in that specific category, which happens to be the Company News category for me.
You can either remove this parameter to display all weblog posts, or change it to reflect the category ID of your Company News category. You can find that ID by visiting the Category Management interface for your Weblog Category Group in the Control Panel. If you click the Add/Edit Categories link for your group, the ID’s will appear at the left of the list.
You’ll also need to change the link to reflect the names of your Template Group and weblog/comments template, if you’ve named them differently than I have in this tutorial.
Note that I’m again using some of the plugins we covered in Chapter 13 to format the Latest Products sidebar content.
Once you’ve made your tweaks, save the template and re-visit your site. The new dynamic content should appear (this is always one of those moments I really enjoy working with EE - one saved template and most of the pages on my site are now updated showing real content).
The Contact Form
Most business sites will want, in the very least, a simple contact form and EE can handle that with out-of-the-box functionality. If your needs are more advanced—wanting to save form submissions in a database table, more advanced error checking, user messages, etc. - then you’ll want to look into the popular FreeForm module from Solspace.
Note: the Email Module isn’t available in the Core version of EE, so if you’re following along in Core you’ll have to skip this step.
Here’s what you’ll need to do to get a basic contact us form working with EE code:
- Turn on the Email Module
- Copy my Contact Us template
- Tweak the template
- Update your main navigation
- Test
Turn On the Email Module
The contact form requires the EE Email Module, which isn’t installed by default. To install it, visit the Modules tab in the EE Control Panel, and the Email Module will show up around #4. Click the Install link to enable the Email Module.
The Contact Us Template Code
Here is the code for the site/contact template. This template should be created in your main site Template Group:
{assign_variable:my_embedded_template_group="embeds"}
{embed="{my_embedded_template_group}/html_header" my_page_title="Contact"}
<body>
<div id="content">
{embed="{my_embedded_template_group}/logo_title"}
{embed="{my_embedded_template_group}/main_nav" my_location="contact"}
{embed="{my_embedded_template_group}/search_section_intros" the_url_title="contact"}
<div id="maincontent">
<div id="right_side">
{embed="{my_embedded_template_group}/latest_news"}
{embed="{my_embedded_template_group}/latest_products"}
</div><!-- close right_side -->
<div id="left_side">
{exp:email:contact_form user_recipients="false" recipients="youraddress@yourdomain.com" charset="utf-8" return="{homepage}|Home Page"}
<h2 class="underline">Contact Us</h2>
<p>
<label for="from">Your Email:</label><br />
<input type="text" id="from" name="from" size="40" maxlength="35" />
</p>
<p>
<label for="subject">Subject:</label><br />
<input type="text" id="subject" name="subject" size="40" value="Contact Form" />
</p>
<p>
<label for="message">Message:</label><br />
<textarea id="message" class="textarea" name="message" rows="18" cols="40"></textarea>
</p>
{if captcha}
<p>Please enter the word you see in the image below:</p>
<p>{captcha}<br />
<input type="text" name="captcha" value="" maxlength="20" /></p>
{/if}
<p><input name="submit" class="submit_button" type='submit' value='Send Email' /></p>
{/exp:email:contact_form}
</div><!-- close left side div -->
</div><!-- close main content div -->
{embed="{my_embedded_template_group}/footer"}
</div> <!-- close content div -->
</body>
</html>
Tweak the Template
You’ll need to edit the “assign variable” at the top of the template to specify the name of your embedded Template Group, if it’s not “embeds.“
You’ll also need to make some changes to the opening exp:email:contact_form tag. Put the email address you want to receive the email in the “recipients” parameter.
Update Main Navigation
You’ll now need to edit your embeds/main_nav template. Here’s what mine looks like now:
<div id="menu">
<div class="submit">
<ul>
<li><a{if '{embed:my_location}'=="home"} class="selected"{/if} href="{homepage}" ><span>Home</span></a></li>
<li><a{if '{embed:my_location}'=="about"} class="selected"{/if} href="/index.php/about/"><span>About</span></a></li>
<li><a{if '{embed:my_location}'=="products"} class="selected"{/if} href="/index.php/products/"><span>Products</span></a></li>
<li><a{if '{embed:my_location}'=="services"} class="selected"{/if} href="/index.php/services/"><span>Services</span></a></li>
<li><a{if '{embed:my_location}'=="weblog"} class="selected"{/if} href="/index.php/weblog/"><span>Weblog</span></a></li>
<li><a{if '{embed:my_location}'=="contact"} class="selected"{/if} href="/index.php/contact/"><span>Contact</span></a></li>
</ul>
</div>
</div>
Test the Form
Load the form in your browser, and give it a whirl. If the email doesn’t come through, try sending yourself an email using the Communicate tab of the Control Panel. If still no go, you might need to visit the email configuration section found at CP Home > Admin > System Preferences > Email Configuration, and have a conversation with your webhost about which email protocol to use. With Train-ee.com on EngineHosting, I’m using the PHP mail option successfully.
CAPTCHAs for Contact Us Form
The template provided has the code for CAPTCHAs, but you have to enable them before they’ll show up.
The setting is also found on the Email Configuration screen of the Control Panel. Set Enable CAPTCHAs for Tell-a-Friend and Contact Emails to Yes. And remember, they won’t show for you while you are logged in.
I’ve found it easiest to debug/test CAPTCHAs by being logged in one browser (usually Firefox) and logged out in another browser (usually IE). This way you can make template tweaks and see the changes without constantly having to log in and out.
The Results
Here’s my working example of a contact form.
Search Engine Caveats
And for my final trick…hooking up the EE search engine. But first, some caveats.
EE’s supplied search engine doesn’t function like high-end search engines in that it doesn’t roll through your site, looking at and indexing your rendered pages. In my mind I think of that as an “outside-in” search, where a spider would just see your site as a collection of HTML pages as it comes out in the browser.
EE’s search is more of an “inside-out” approach, where it searches at the database level first then, when it finds a match, needs to be told where that database content is supposed to show up on the site. Because of this there are some inherent limitations that will affect your results:
- Content that is re-used will not get multiple hits. For example - if your search contained words that were contained in the Latest News sidebar we created above, an outside-in search engine would return hits for every page/section on the site. EE’s inside-out search engine will return one hit, mapped to the weblog/comments template for that weblog entry.
- Content in our Miscellaneous Content Weblog cannot be searched. We’ve used this weblog to hold snippets of text that get reused around the site, but they don’t have a “home template” for us to map EE to, so it’s best to exclude them from the search.
- Category content cannot be searched. EE 1.6.1 has increased category capabilities with its category custom fields, but anything stored at the category level isn’t currently included in the search.
Hooking Up the Search Engine
Let’s again implement the native EE search engine, and you can decide if it meets your needs or not. To fully implement the search function, you’ll need to:
- Update your embeds/search_section_intros template to include the EE Simple Search Form tags.
- Create a new Template Group for the search related templates.
- Create a template that loads when there are no results.
- Create a template to display results.
Updating the Search and Section Intro Template
In your embeds Template Group, you should have a template called search_section_intros that contains the code for the search box & submit button. Here is the new code for that template:
<div id="subheader">
<div class="rside">
<div class="padding">
<div id="search">
{exp:search:simple_form weblog="about|home|products|services|weblog" no_result_page="search/noresults" result_page="search/index" search_in="everywhere"}
<p>
<input type="text" name="keywords" id="keywords" value="" size="20" maxlength="250" class="text" />
<input type="submit" value="" class="btn1" />
</p>
{/exp:search:simple_form}
</div>
</div>
</div>
<div class="lside">
<div class="padding">
{exp:weblog:entries weblog="misc_content" limit="1" dynamic="off" disable="categories|trackbacks|member_data|pagination" url_title="{embed:the_url_title}" }
{page_body}
{/exp:weblog:entries}
</div>
</div>
</div>
Search Notes
With this code we are using the EE Simple Search Form tags. You can review the Simple Search documentation.
There is also an Advanced Search tag set if you want to offer users the ability for more targeted searches.
The parameters you’ll need to tweak are the names of the weblogs, and the names of the no results and results templates - which we’ll load next. The other parameter you can look at is the “search_in”. I’ve set it to “everywhere” since we have comments on this site.
The important thing to remember when integrating the EE Simple Search Form tags with an existing design is that the style can be provided by the design through the use of the name and class parameters, but EE needs the “name=keywords” to stay.
OK - save the updated code in that template and let’s load up the results and no results templates.
Create a Search Template Group
Your installation of EE might include a Template Group for search templates already. If so, keep the group and just rename all existing templates (I don’t like to delete the default ones as they are often valuable for grabbing code snippets from).
To rename templates, select the Template Group, then click the Preferences link in the center column. I usually just preface existing names with “zz_” so they will sort to the bottom.
EE will not let you rename the search/index template, so if you want to save a copy of that one you will have to go through the process of creating a new template and copying the existing search/index template. We will be using the index template to display results so this is a good idea to do.
No Results Template
For these I typically just create a dedicated template, but again use the Miscellaneous Content Weblog as a source for the messages that are displayed. This approach lets my clients control those messages easily. So to get this working we need to:
- Load and tweak the no results template
- Create two new entries in the Miscellaneous Content Weblog
- Test
Copy the No Results Template
Here’s the code for the search/noresults template:
{assign_variable:my_embedded_template_group="embeds"}
{embed="{my_embedded_template_group}/html_header" my_page_title="Search | No Results"}
<body>
<div id="content">
{embed="{my_embedded_template_group}/logo_title"}
{embed="{my_embedded_template_group}/main_nav" my_location=""}
{embed="{my_embedded_template_group}/search_section_intros" the_url_title="please-try-again"}
<div id="maincontent">
<div id="right_side">
{embed="{my_embedded_template_group}/latest_news"}
{embed="{my_embedded_template_group}/latest_products"}
</div><!-- close right_side -->
<div id="left_side">
{exp:weblog:entries weblog="misc_content" disable="pagination|categories|member_data|trackbacks" url_title="no-results" dynamic="off"}
<h2 class="underline">{title}</h2>
{page_body}
{/exp:weblog:entries}
</div><!-- close left side div -->
</div><!-- close main content div -->
{embed="{my_embedded_template_group}/footer"}
</div> <!-- close content div -->
</body>
</html>
Create New Miscellaneous Content Entries
The new search/noresults template assumes two new entries:
- The section intro entry that appears next to the search bar in the green area. This entry needs a URL Title of “please-try-again.” Enter some text and save.
- The Page Body content. The entry needs a URL Title of no-results. Enter some sort of sympathetic “we’re sorry” text and save.
Note that this template doesn’t exist in the main navigation for the site, so I’m passing an empty string to the main navigation for the location value. This ensures that the main navigation isn’t “lit up” for this template.
Test
You should now be able to test your no results operation. Re-visit your site, refresh the page to ensure you’ve got the latest, and enter in a non-sensical search term that you know doesn’t appear on the site. You should get the new search/noresults template as a result, with the messages you created in the Miscellaneous Content Weblog.
Search Results
With the no results handled, let’s move on now to the search results. We’ll be using the Search Results tag, but implementing it in a vastly simplified fashion that just feels better for this site. You can review the documentation for the Search Results tag.
Our process here will be:
- Editing the search/index template
- Creating a “results found” entry in the Miscellaneous Content Weblog
- Going through our weblog configurations, making sure the search results path is specified, and the excerpt field is specified
Edit the Search Template Group Index Template
Here’s the code for this template:
{assign_variable:my_embedded_template_group="embeds"}
{embed="{my_embedded_template_group}/html_header" my_page_title="Search | Results"}
<body>
<div id="content">
{embed="{my_embedded_template_group}/logo_title"}
{embed="{my_embedded_template_group}/main_nav" my_location=""}
{embed="{my_embedded_template_group}/search_section_intros" the_url_title="results-found"}
<div id="maincontent">
<div id="right_side">
{embed="{my_embedded_template_group}/latest_news"}
{embed="{my_embedded_template_group}/latest_products"}
</div><!-- close right_side -->
<div id="left_side">
<h2 class="underline"> {exp:search:total_results} Result(s) for {exp:search:keywords}</h2>
<ul>
{exp:search:search_results switch="resultRowTwo|resultRowOne"}
<li class="search_results"><b><a href="{auto_path}">{title}</a></b> from <em>{weblog}</em><br/>{excerpt}<br/></li>
{/exp:search:search_results}
</ul>
</div><!-- close left side div -->
</div><!-- close main content div -->
{embed="{my_embedded_template_group}/footer"}
</div> <!-- close content div -->
</body>
</html>
Paste that into your new template, and tweak any names/paths necessary for your installation.
Section Intro
By now you should be able to look at the template code and realize that it’s going to be looking for a section intro from the Miscellaneous Content Weblog.
So go ahead and publish one, this time with a URL Title of results-found.
Search-Specific Variables
You’ll note that we have a couple new variables being displayed on this template - one for total hits and one that displays the keywords that were passed to the search:
{exp:search:total_results} Result(s) for {exp:search:keywords}
You’ll also note that each result has a couple of variables in each list item - and these we need to look at more closely:
<li class="search_results"><b><a href="{auto_path}">{title}</a></b> from <em>{weblog}</em><br/>{excerpt}<br /></li>
First let’s tackle the auto_path.
This variable is where EE holds that mapping of database content to template location I spoke of earlier. If you look at the documentation for this variable you’ll see that it’s set in Admin > Weblog Administration > Weblog Management > Edit Weblog Path Settings > Search Results URL.
So let me provide you a list of how I’ve setup each weblog for this tutorial, and its Search Results URL setting. Note that you can use the homepage variable – handy for sites that get constructed at a temporary URL, then moved once they go live. Using the homepage variable here will prevent you from having to revisit these paths during the go-live process.
About:
{homepage}/site/about/
Home
{homepage}/site/
Products
{homepage}/products/detail/
Services
{homepage}/services/detail/
Weblog
{homepage}/weblog/comments/
Basically - where the section is configured with single-view templates I link to them. If there is no single-view template, I link to the multi-entry view - knowing that when the search results are formatted EE will append on the URL Title which will have the effect of making the multi-view template display only the one entry.
Now let’s tackle the excerpt variable. This is also a per-weblog setting, and is found in Weblog Administration > Weblog Management > Administrative Settings > Which Field Should Be Used for Search Excerpt?
Typically I just pick the field that will, on average, have the most content for that weblog. For our weblogs above it’s the Page Body field for the Home, About and Services weblogs, the Description field for Products, and the Body field for the Weblog.
With those configurations saved you should be able to use your search engine with terms that you know appear in the content, and get results. The results should have links that take you to that entry on the site, using the template you’ve specified.
Keep In Mind
Keep in mind that, on the search results template, you can use conditionals and “nearly all” of the variables, etc. from the weblog:entries tag - in addition to plug ins, etc. I’ve built more complex search results templates with these extra tools that in the end performed a bit better than the defaults - but at least you know have a starting point.
Are Your Fields Searchable?
Not seeing the results you expect?
Here’s another thing to remember: each field in EE is configurable to be searchable or not. Now would be a good time to run through all your fields and make sure they are configured properly. The setting can be found in Admin > Weblog Administration > Field Groups > Custom Fields. Choose your Field Group, then your field. Scroll down to where it says Is Field Searchable? and make sure that it’s set to Yes.
Updating the Footer
Oh - one small change I hadn’t noted anywhere. Now that the site’s main sections are fully implemented, you can go back to the Miscellaneous Content entry that’s holding your footer content and update the links. I got rid of the links to the HTML and CSS validator in order to make room to replicate the main navigation with text links.
You’ve Come A Long Way, Baby!
With these latest changes, you should have a fully functional small business website implemented on ExpressionEngine. My completed working example site is here.
The Takeaways
Here’s what you should have learned by making it all the way through this tutorial:
- That any design can be powered with EE – giving you complete control over the visuals without worrying if EE can “do that”.
- How to chunk up HTML for integrating into EE – taking advantage of embedded templates for easier code maintenance.
- How to organize Template Groups and Templates for semantic URLs – letting you apply good SEO techniques for your clients.
- How to store page content in weblog posts – which will allow your clients to maintain their content without having to mess around in the presentational code.
- How to use categories – letting you organize content into deeper levels in areas of your site to accommodate product catalogs, etc.
- How to use custom category fields – letting you use Categories more often for more extended purposes for better content organization on the site.
- How to relate content together using Categories – letting you present content alternatives and upsell opportunities on client sites.
- How to use EE Global Variables and Embedded variables to make your coding life easier.
- How to implement at Contact form to allow site visitors to contact your clients.
- How to implement a search engine so site visitors can find what they are looking for.
Thanks!
Thank you ever so much for reading this tutorial - and please stay tuned to Train-ee for some of the other EE training that’s in development.
Category Navigation






by I Hussey
Date: Friday, November 7th, 2008
Comment: #1
A usefull set of tutorials these have taken me all day and it is not my first encounter with EE. The thing I did like about this set of tutorials was the use of the html template being primarily a programmer but aiming to be a designer the use of templates it very beneficial for the likes of me. Thanks for all the hard work. Now I will go back and fix my category errors with products and services…