HTML Markup I don't know about you, but as a Web Developer I sometimes find myself not doing the things I should be doing. The recent rash of SQL Injection script attacks have shown me personally how little thought I sometimes give to where the input is coming from when I'm developing forms.

Then there is the generated markup itself. All our development efforts end up in plain HTML being spit out onto a'page' on a device of some kind. When you consider how sensitive the search bots are to the structure, content and placement of our markup, isn't it amazing that the only time we ever think of it is when we have to generate it dynamically in some code-behind? :-O

If you are using master pages, then you won't want to have duplicate content, in the shape of similar meta tag content, all over your site. So, you will have to generate the meta tags programmatically in the code-behind of the content pages:

HtmlHead head = this.Master.Page.Header;
HtmlMeta meta = new HtmlMeta();
meta.Name = "Description";
meta.Content = "Friendly and relevant content";
head.Controls.Add(meta);

 

You also do not want pages in the secure area of your site to be spidered:

HtmlHead head = this.Master.Page.Header;
HtmlMeta meta = new HtmlMeta();
meta.Name = "googlebot";
meta.Content = "noindex, nofollow";
head.Controls.Add(meta);

 

I recently noticed a big chunk of JavaScript in the markup that I was using to solve the problem of pushing the footer to the bottom of the page, and not relying on copious amounts of needless content and spacers to do the job that CSS cannot. I should have had it in an external file and used the appropiate ASP.NET method to register it and pull it in. So, I created a JS file called footerFix.js, placed it in its own folder and used the following in the master page code-behind:

string myScript = "/js/footerFix.js";
Page.ClientScript.RegisterClientScriptInclude("myKey", myScript);

 

This created the following markup in my page:

<script src="/js/footerFix.js" type="text/javascript"></script>

 

Now I have a smaller page, faster download time and a fairly good chance of the spiders actually getting the info they require.

 



Comments (5) -

Extensive SEO
Extensive SEO United States
9/25/2008 6:41:57 PM #

Going alog with you comments on Meta Tags. Josh Salwin has a very good Blog post that I have Utilized in My site. Here is the URL:
www.joshsalwen.com/.../

agrace
agrace United States
9/25/2008 6:59:30 PM #

Thank you for the link. Note: App_Code folder does not play nice with the Web Application project template, but some good info in that article Smile

agrace
agrace United States
10/3/2008 9:42:20 AM #

I came across a blog posting by Adam Tibi which shows a really simple way of doing this declaratively:

http://www.adamtibi.net
Article: Three Rules That ASP.NET Developers Should Know About SEO.

Anthony Smile

agrace
agrace United States
11/14/2008 9:41:45 AM #

Update: this is the way I am currently implementing this:

http://www.codeproject.com/KB/aspnet/PageTags.aspx
weblogs.asp.net/.../421405.aspx

Deepak Anmol
Deepak Anmol India
5/9/2009 10:40:35 AM #

Step 1 - default.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Default.master.cs" Inherits="MetaSpike.Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "www.w3.org/.../xhtml1-strict.dtd">;

<html xmlns="http://www.w3.org/1999/xhtml"; >
    <head runat="server">
        <title></title>
       <asp:ContentPlaceHolder id="MetaDescriptionHolder" runat="server" Visible="false"></asp:ContentPlaceHolder>
        <asp:ContentPlaceHolder ID="MetaKeywordsHolder" runat="server" Visible="false"></asp:ContentPlaceHolder>
    </head>
    <body>
        <form id="DefaultMasterForm" runat="server">
            <div>
                <asp:ContentPlaceHolder ID="MainContentHolder" runat="server"></asp:ContentPlaceHolder>
            </div>
        </form>
    </body>
</html>

Step 2 - default.master.cs

using System;
using System.Web.UI;

namespace MetaSpike {
    public partial class Default : MasterPage {

        protected override void OnInit(EventArgs e) {
            base.OnInit(e);

            this.MetaDescriptionHolder.Load += new EventHandler(MetaDescriptionHolder_Load);
            this.MetaKeywordsHolder.Load += new EventHandler(MetaKeywordsHolder_Load);

            this.Page.LoadComplete += new EventHandler(Page_LoadComplete);
        }

        private void MetaDescriptionHolder_Load(object sender, EventArgs e) {
            throw new NotImplementedException();
        }

        private void MetaKeywordsHolder_Load(object sender, EventArgs e) {
            throw new NotImplementedException();
        }

        private void Page_LoadComplete(object sender, EventArgs e) {
            throw new NotImplementedException();
        }
    }
}

Step 3 - default.master.cs (continued)

using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace MetaSpike {
    public partial class Default : MasterPage {
        private HtmlMeta descriptionMeta;
        private HtmlMeta keywordsMeta;

        protected override void OnInit(EventArgs e) {
            base.OnInit(e);

            this.MetaDescriptionHolder.Load += new EventHandler(MetaDescriptionHolder_Load);
            this.MetaKeywordsHolder.Load += new EventHandler(MetaKeywordsHolder_Load);

            this.Page.LoadComplete += new EventHandler(Page_LoadComplete);
        }

        private void MetaDescriptionHolder_Load(object sender, EventArgs e) {
            string content = this.ParseHolderContent(this.MetaDescriptionHolder);

            if (string.IsNullOrEmpty(content)) return;

            this.descriptionMeta = new HtmlMeta();
            this.descriptionMeta.Name = "description";
            this.descriptionMeta.Content = content;
        }

        private void MetaKeywordsHolder_Load(object sender, EventArgs e) {
            string content = this.ParseHolderContent(this.MetaKeywordsHolder);

            if (string.IsNullOrEmpty(content)) return;

            this.keywordsMeta = new HtmlMeta();
            this.keywordsMeta.Name = "keywords";
            this.keywordsMeta.Content = content;
        }

        private void Page_LoadComplete(object sender, EventArgs e) {
            Page page = sender as Page;
            if (page == null) return;

            if (this.descriptionMeta != null) page.Header.Controls.Add(this.descriptionMeta);
            if (this.keywordsMeta != null) page.Header.Controls.Add(this.keywordsMeta);
        }

        private string ParseHolderContent(ContentPlaceHolder holder) {
            if (holder == null || holder.Controls.Count == 0) return string.Empty;

            LiteralControl control = holder.Controls[0] as LiteralControl;
            if (control == null || string.IsNullOrEmpty(control.Text)) return string.Empty;

            return control.Text.Trim();
        }
    }
}

Step 4 - home.aspx

<%@ Page Language="C#" MasterPageFile="~/Default.Master" AutoEventWireup="true"
    CodeBehind="Home.aspx.cs" Inherits="MetaSpike.Home" Title="Meta Spike Home" %>
    
<asp:Content ID="MetaDescription" ContentPlaceHolderID="MetaDescriptionHolder" runat="server">description goes here</asp:Content>
<asp:Content ID="MetaKeywords" ContentPlaceHolderID="MetaKeywordsHolder" runat="server">keywords, .net, asp.net, meta</asp:Content>

<asp:Content ID="MainContent" ContentPlaceHolderID="MainContentHolder" runat="server">
    this page now has a very simple mechanism for adding and updating meta tags! enjoy!
</asp:Content>

Step 5 - view source rendered home.aspx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "www.w3.org/.../xhtml1-strict.dtd">;

<html xmlns="http://www.w3.org/1999/xhtml"; >
    <head>
        <title>Meta Spike Home</title>
        <meta name="description" content="description goes here" />
        <meta name="keywords" content="keywords, .net, asp.net, meta" />
    </head>
    <body>
        <form name="aspnetForm" method="post" action="Home.aspx" id="aspnetForm">
            <div>
                <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
       value="/wEPDwUJNDMyNDU0NjAzZGQfTG4D56NhuIUPL9dxPlf1j85RXw==" />
            </div>
            <div>              
                this page now has a very simple mechanism for adding and updating meta tags! enjoy!
            </div>
        </form>
    </body>
</html>

Some things to note:

    * ContentPlaceHolders on the MasterPage have Visible set to false
    * the use of the Page's LoadComplete event instead of Load
    * only straight text in the Content tags on Home.aspx, ASP.NET will put that text into LiteralControls
    * no text in the Content tags on Home.aspx will result in no META tags being output (good thing)

Pingbacks and trackbacks (2)+