How to Get Your Silverlight Pages Indexed By Search Engines

Use the HTML DOM to add dynamic Title, Keywords and Description tags to your Silverlight Pages

There are a lot of articles and tips about "deep linking" and so on with Silverlight.

But, the bottom line is that if you want your Silverlight pages properly indexed by Google and its brethren, you need to be able to dynamically add TITLE, META KEYWORDS and META DESCRIPTION Tags to the hosting page. Here we will show not only how to do this from within a Silverlight application, but also how to do it in response to a search engine crawler.

In a nutshell, search engines follow hyperlinks, and then index any content they find. They collect any additional links they find on the page and crawl those. If you have a Silverlight application that has multiple user controls that respond to user navigation, but they are all hosted in the same page that has a TITLE tag of "My Cool Silverlight Application" and no dynamic META Description or META keywords tags, you really haven't accomplished much from an SEO (search engine optimization) standpoint. This doesn't even take into account the fact that all your "content" may be inside your Silverlight app, which renders it 100% invisible to search bots. You may actually need to consider having some "relevant content" in the HTML page itself to get real search engine action.

The way that your "Page" gets found by a search engine is either you submitted it, it is listed in your sitemap.xml file, or there is a hyperlink to it from somewhere else, perhaps even from another page in your own website. There are other "deep linking" techniques that will allow Silverlight content to be custom-presented based on what is on the QueryString in a unique search-engine optimized url, but I'll save those for another article.

You can add these tags to a page directly from within your Silverlight Application itself with the following code. You can also use this same technique to inject relevant content into the HTML of the page where it will be indexed. The end result will be that your Silverlight "Page" will end up being the target of more search results on Google, Bing, Yahoo and oher search engines, and you can combine this technique with the deep-linking properties of, for example, a Silverlight Navigation app to get much better search engine result rankings.

First, in your App.Xaml.cs codebehind class, add the following static method:

public partial class App : Application
{
public App()
{
this.Startup += this.Application_Startup;
this.Exit += this.Application_Exit;
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
public static void SetPageInfo (string keywords, string title, string description)
{
ScriptObjectCollection soc = HtmlPage.Document.GetElementsByTagName("Title");
if (soc != null && soc.Count > 0)
{
HtmlElement titleElement = (HtmlElement)soc[0];
// string mytitle = (string)titleElement.GetProperty("innerHTML");
HtmlPage.Document.SetProperty("title", title );
HtmlElement headElem = HtmlPage.Document.GetElementsByTagName("head")[0] as HtmlElement;
HtmlElement keys = HtmlPage.Document.CreateElement("meta");
keys.SetAttribute("name=\"keywords\" content", keywords);
headElem.AppendChild(keys);
HtmlElement desc = HtmlPage.Document.CreateElement("meta");
desc.SetAttribute("name=\"description\" content", description);
headElem.AppendChild(desc);
}
}

NOTE: Apparently Firefox does not like SetAttribute. Use SetProperty instead.

Then in your Main page codebehind, you can call the method like this:

public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
App.SetPageInfo("test,test2,test3","This is the title", "This is the description");
}
}

Incidentallly, astute readers might wonder why I am doing this, setting both the name attribute and the content attribute "in one go":

keys.SetAttribute("name=\"keywords\" content", keywords);

The answer is, that's the only way I could get this to work! Otherwise, I would get a <meta keywords="X,Y, Z""> without the name attribute. Go figure....

If your Silverlight Application has multiple pages or uses the Navigation framework, you can do this for each page in your application, setting a different Title, meta keywords and meta description tag dynamically.

If you want the search engines to index your Silverlight content, don't expect them to dig into your XAP file and parse the text - not only is it unlikely they'll do it - but you might not want them to anyways.

Search engines want to see, at a minimum, a Page TITLE element and a META Description element. Give them what they want, and your pages that contain Silverlight content will be correctly indexed!

It irks me to no end to see people with blogs that have excellent multiple content pages, and yet every single one has the same Page Title tag that says, "My Blog"! If you give Google, Bing, Yahoo et. al. garbage - they're going to give you garbage back, and your search results will reflect this.

You MUST have a unique, keyword - dense Page TITLE and META Description tag for every page on your blog or website. Most search engines will use your META Description tag content verbatim. If this tag is missing, they'll come up with their own, and you may not like it.

If you View Source from the browser, you will not see these elements because they have been dynamically added to the page. But by using a little Javascript, you can easily see that they are in the page:


javascript:document.write(%22%3Cxmp%3E%22+document.documentElement.innerHTML+%20%22%3C/xmp%3E%22);

You can copy and paste the above snippet into the address bar of your browser to see this at work.

The downloadable Visual Studio 2008 solution has the above javascript in an A HREF link right in the test page.


Next Stage: Feed the Bots!

Jim McCurdy astutely pointed out that while the above may be useful, it is still not visible to crawlers. The crawler simply downloads all the markup in the page, but the Silverlight plugin is never instantiated. In order for a Silverlight Application to "come to life", it must exist in a live browser DOM. Jim shows a solution using urlrewriting. However, it can be done with an even simpler solution - detection of bots via their User-Agent and writing the custom content directly into the same page.

Let's add a couple of utility methods to our ASP.NET web project's Global.asax codebehind:

public static bool IsBot()
{
if( HttpContext.Current.Request.UserAgent==null)
return false;
string userAgent = HttpContext.Current.Request.UserAgent.ToLower();
string[] botKeywords = new string[] { "bot", "spider", "google", "yahoo", "search", "crawl", "slurp", "msn", "teoma", "ask.com" };
bool isBot = false;
foreach (string bot in botKeywords)
{
if (userAgent.Contains(bot))
{
isBot = true;
break;
}
}
return isBot;
}
public static void PlaceMetaTags (string title, string keywords, string description, Page page )
{
System.Web.UI.HtmlControls.HtmlMeta metaKeywords = new System.Web.UI.HtmlControls.HtmlMeta();
System.Web.UI.HtmlControls.HtmlMeta metaDescription = new System.Web.UI.HtmlControls.HtmlMeta();
page.Title = title;
metaKeywords.Name = "Keywords";
metaKeywords.Content = keywords;
metaDescription.Name = "Description";
metaDescription.Content = description;
page.Header.Controls.Add(metaDescription);
page.Header.Controls.Add(metaKeywords);
}

"IsBot" simply compares the User-Agent string to a known list of keywords, and returns true or false. And "PlaceMetaTags" provides a convenient way to write a custom title, meta - keywords and meta -description tag. Both of these methods, since they are static and public, will be availalble from any page in your web site via "Global.MethodName..."

So to test this, I've constructed a "test page" that uses the WebClient class to request our Silverlight page after setting a "fake" GoogleBot User-Agent:

WebClient wc = new WebClient();
wc.Headers.Add("user-agent", "Googlebot/2.1 (+http://www.google.com/bot.html)");
string s = wc.DownloadString("http://localhost:4403/Default.aspx");
this.txtBox1.Text = s; // show the crawled HTML

what will happen now if you run the "WebForm1.aspx" page in the sample solution is that the page detects that the request is from a "bot", and you will see the crawled HTML in the textBox with:

<head id="Head1">
<title> Title for Bots!</title>
....
<meta name="Description" content="The description I want bots to see" /><meta name="Keywords" content="BotKeyword1, botkeyword2" />
</head>

And all is good. We've accomplished two goals: Be able to dynamically write Title and Meta tags from within a Silverlight application (useful when the page is viewed in a browser, as in "real life"), and also the ability to detect when a search engine crawler has requested the page, and provide the crawler with meaningful tags to index. Both of these approaches represent useful tools you'll definitely want to include in your Silverlight Application "toolkit".


You can download the complete solution here.



By Peter Bromberg   Popularity  (6357 Views)