Wednesday, August 25, 2010

Geo-location Provides Badges and Tests User Privacy

A Conversation Between Two Social Media Nerds

Shane and I have been randomly discussing geo-location during meetings and while eating our lunch for months now. We gently argue back and forth about how fun it is, how silly it is and how safe it is. Shane is adamant about becoming the mayor of a local Mexican food joint. I on the other hand know that no one is interested in where I eat lunch or get my coffee. When I caught wind last Wednesday that Facebook would be launching Facebook Places later that evening, I thought it was a perfect opportunity to put our rants out there for everyone to "enjoy."

Q1: What is your preferred geo-location based app? Why?

Shane: When it comes right down to it I haven’t found any hugely beneficial qualities to location based apps so trying to answer why I chose the one I have now is a hard question to answer. Prior to reading the recent press about Facebook Places I had never even considered there were options other than Foursquare. Initially, the only reason I started playing with Foursquare was that it was new, it was generating a little buzz and being in the technology business I think it’s my duty to at least give some of these things a go…not dissimilar to why I started using Friendster back in 1997. Then, as I started travelling more, it only made sense to check-in on Foursquare because they would automatically update Twitter and Twitter would update Facebook. Therefore I was able to passive-aggressively brag to all my friends that I was now going to a Cubs game while they were stuck in the office. On top of that I do enjoy having a history of what I was doing and where I was at. Call it a lazy man’s journal which now happens to include corresponding pictures thanks to Flickr. I only have one mayorship (which is a slightly compelling reason for me to continue using Foursquare) and I do have a few friends that use it so I see no reason to switch platforms at the moment.

Alisa: I have never used any of the various geo-location applications. I also disabled the Facebook Places check-in options last week as soon as I learned how to opt out of them. It's not that I do not see the value in geo-location in terms of analyzing social behavior, it's simply that I deeply value my privacy and I don't see the purpose of checking in to my local sandwich shop or favorite watering hole. Even if I was offered an incentive to do so, my privacy is worth more to me than $1 off my mocha or 10% of my dining bill.
On the privacy note, some people have asked me, "Why participate in the social media world if you are so protective of your privacy?" And my answer is simple, "I participate in social media to communicate with my friends and family who I know and trust. The rest of the world doesn't need to know what I am doing or how I live my life ... not that the rest of the world would care to begin with. Information on the internet tends to 'live forever' and in 100 years no one needs to know that I have cute puppies or enjoy a certain neighborhood cafe."

Q2: How are both small businesses and large corporations taking advantage of geo-location and what value does geo-location provide to businesses?

Shane: At this point, and having used Foursquare for about a year now, the only place I can remember offering me a discount based on my Foursquare check-in was Hash House A Go Go in Vegas. Interestingly enough I would have never remembered what the name of that place was had I not been able to go back through my Foursquare history. Showing the server my check-in, I was offered a discount on a drink. Nothing earth shattering but enough to make me check-in. Would my decision to check-in be different were I offered a free pair of Spock ears at this year’s Official Star Trek convention…undoubtedly so.
At the moment I don’t see any huge beneficiary of location based services. On the other hand I could see that changing though in favor of the SMB market. Granted, the Starbucks of the world can implement a rewards program for thousands of franchises all over the country but how many Fortune 500 companies are going to go to the effort. In the grand scheme of things there are a lot more mom & pop, Tex’s Cafés out there than there are McDonalds and Applebees so it seems like the success of the technology may depend more on the 99.7% of small businesses rather than the .3% of large corporations. The problem with that…the owners of Tex’s Café aren’t the type of folks using Foursquare. Google sent 100,000 ‘Favorite Places’ stickers to local business all across the country. I don’t know what the cost of that was but I would suggest Foursquare start focusing some marketing dollars on building up vendor awareness rather than user awareness.

Alisa: I know Starbucks and Ann Taylor are two national retailers that have run Foursquare promotions. The funny (or sad) thing is when I tried to get the details of each promotion, I was directed to articles on Mashable and was not able to easily locate a link to the promotion on either company's official website. Believe me, I understand that both establishments were running social media campaign promotions, therefore they may have only promoted said offers through social media channels. I just find it interesting that they are targeting people who already know about geo-location technology, which I believe the most recent registration data is that Foursquare is approaching three million users.

In terms of value, Mosaic, a downtown Saint Louis restaurant and lounge, heavily promoted their Foursquare promotion this past May and from everything I've heard and read, it was wildly successful. I agree with Shane that geo-location promotion success may skew towards the small business community.

Q3: How are geo-location based applications profitable?

Shane: Today I don’t think businesses are investing thought into the process to make it profitable. In fact, most places could put a sign on the door that says “10% off for Foursquare Mayors” and I’d likely give it a try. Not necessarily because their product is superior to their next door neighbor but more because I know they’re catering to me. Unfortunately most businesses right now aren’t making a big enough deal out of it. If you have the clientele that is A) tech savvy and B) competitive then offering a significant prize to a mayor may be enough to keep me coming back. If nothing else put a sign on the cash register that says “Have you checked in yet?” If I’m not a current customer and see my friends checking in there’s a little brand awareness you didn’t have before. And best of all, it’s FREE! In some respects this is just another extension of the same old social media/ROI question. We all know social media has value but in a lot of cases that’s very difficult to prove. I would say location based services are very similar at the moment. Not enough people are spending the time and creativity necessary to put together location based campaigns. Once that starts happening more data will become available that should help to prove out the model.

Alisa: I've never asked a local business that offers geo-location applications check-ins and/or promotions if they have analyzed their customer user data to identify any trends or success stories. Obviously, I mentioned the Mosaic campaign above, but I don't have first hand knowledge of their success. In fact I've only heard of one other Foursquare mayor promotion other than the three I referred to above. Perhaps because I do not use the applications, I am simply not looking to check-in therefore I am not aware which places I frequent that offer discounts or special badges to their customers. With that said though, my particular consumer behavior would not change if I was offered $1 off my mocha or 10% off my dining bill by checking in and achieving some virtual political status. But that's just me.

Q4: Is there a niche for B2B geo-location services?

Shane: Up to this point I think when we talk about geo-location services, the check-in based applications have gotten most of the media attention. Looking specifically at that model I don’t see many tremendous B2B opportunities as of yet. The one-to-many, and personal, relationship of check-in based services doesn’t lend itself well to the B2B world. At some point it would be nice if my check-in at the airport could be tied to some corporate perks or an expedited check-in line but I’m not sure the juice is worth the squeeze. On the other hand there are so many other B2B geo based services already in place that we don’t even know about. Most of these types of things are happening behind the scenes and if we’re not careful they’re easy to overlook. Comparing real estate prices on zillow.com, mapping of delivery trucks, traffic congestion, location relevant searching and recommendations all make my life a little easier…I just forget how it is they’re happening. While I may be the consumer viewing the data (real estate prices in my area) that service is being provided by a vendor (zillow.com) and those geo-tags or location based assets are being tracked by yet another business (google.com). Therefore, just like any good entrepreneur, be on the lookout for the pain point in any business model that could be lessened by placing data on a map or knowing that a certain activity is happening with x miles of where you’re standing. When this is all said and done I should be able to search for “gas station” on Google, find the area that has the fewest number of markers and know with confidence that if I build my next franchise in that spot I will have a higher than average chance of success. All without paying a dime to some pay economic development or management firm and their over-priced research.

Alisa: I say this with utter humility, I have no idea how geo-location would benefit B2B. Or maybe I do and I just don't want to share it with the world yet because no else can think of a way to make it successful and my thought leader self is going to make millions ...

What do you think about geo-location? Have you received discounts or benefits from checking in somewhere? Are you concerned about your privacy?

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/geo-location-provides-badges-and-tests-user-privacy

Thursday, August 12, 2010

Tackling Fallback Fields and Values in Sitecore

I recently had the opportunity to fight with …. Err … learn about globalization within Sitecore. If you don’t know what Globalization is within Sitecore, then you are reading the right article, because your knowledge on the subject is the same as mine was when I first started working with it. I almost viewed it as the scary monster under my bed, about to tear my feet off the moment the light goes out. But, trudging forward and facing my fears, I pressed on and the outcome was quite surprising. I actually had a lot of fun once I got around some of the major obstacles in my way, the largest and most pronounced being my very own lack of knowledge on this specific subject. So, after beating my head against the wall, sweating profusely for days at a time, and finally consulting an oracle (he looked kind of like a homeless person to me, but I took his word for it) here is what I have found out about Globalization within Sitecore.

Before I begin, let me preface this with the following statement: this post is not an end-all be-all for globalization, just information I happen to remember and care to relate from my experiences. It also only deals with globalization within the context of Sitecore. Good, now that we got that out of the way, we can continue….

As you may or may not know, globalization is just a fancy pants way to say multi-lingual, which is an even more fancy way to say multiple languages. So, if you want multiple languages to display on your site, then you are going to have to use some form of globalization. For the purposes of this post, let us assume that we are dealing with English as your main language and Bangladeshi (just because I like the way it sounds….. Bangladeshi  ) as your secondary language.

In order to create a user-friendly website that caters to both of your demographic groups, we need some form of language switching on the site. Putting a dropdown at the top of your site is easy enough. In this example, we are setting our language embedding to “always”, so the URL of the current page also defines the language context being used. We do this with the following line in the web.config:

<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>

Now when you navigate to a page within Sitecore, you should see something like this: http://www.yoursite.com/en/ItemName.aspx for the English version or http://www.yoursite.com/bgd/ItemName.aspx for the Bangladeshi version.

Create a Bangladeshi versions of “ItemName”, fill it with content, publish, and BLAMO, Bangladeshi content for all to see. Easy enough, right? Yay for out of the box functionality! And for most websites this is all that will ever be required. But let’s get our knees dirty and dig in a bit deeper.

Say we want to fall back to the English version of the page if the Bangladeshi version doesn’t exist. All we do is write a custom pipeline process that will determine if the item exists in the current language, and if it doesn’t, send the user to the /en/ version of the page. This is pretty basic stuff. Here is a quick overview on how to do that if you are interested:

Update web.config with your custom pipeline process. Make sure it’s in the correct location…

<processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel" />
<processor type="YourAssemblyHere.Pipelines.HttpRequest.FallbackLanguageProcessor, YourAssemblyHere " />
<processor type="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel" />

And add the corresponding class to your project…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YourAssemblyHere.Pipelines.HttpRequest
{
public class FallbackLanguageProcessor
{
public void Process(Sitecore.Pipelines.HttpRequest.HttpRequestArgs args)
{
Sitecore.Data.Items.Item contextItem = Sitecore.Context.Item;
if (contextItem == null || contextItem.Versions.Count > 0)
return;


Sitecore.Globalization.Language language = Sitecore.Context.Language;
if (Sitecore.Context.Language.Name != "en")
language = Sitecore.Globalization.Language.Parse("en");
Sitecore.Data.Database contextDatabase = Sitecore.Context.Database;
Sitecore.Context.Item = contextDatabase.GetItem(Sitecore.Context.Item.ID, language);
}
}
}

As you can see, all this does is determine if the current item does NOT have a version (so you are trying to view a Bangladeshi page but it doesn’t exist), get the English version of this page, reset the context, and you are on your merry way. Weeeeeeeeee, isn’t this fun!?!

By this time in the project, I was feeling pretty good about my accomplishments and up to this point wasn’t getting tripped up too much. But alas, a new requirement came down from above: let’s make each FIELD fall back to English if there is no value within the Bangladeshi version. This means that if I go to the About Us page, and I’m in the Bangladeshi context, and there is no About Us page within Sitecore for the Bangladeshi item then I need to display the English version of that page without changing the context of the site! I know, I get a migraine just thinking about it.

Before I continue, I must give you fellow Globalization newbie’s a bit of advice… If you can help it, NEVER display multiple languages to the user on the same page. Not only does this create confusion for the user, it is rather pointless. If the user doesn’t understand English, then why would they ever care to see it on your website? Once you start mixing and matching languages on the same page the context of the site gets confusing for the user. They see content that is in their native language, but the navigation links (some or all of them) are in some foreign language (English in this case). But what the heck right? Let’s see just how extensible Sitecore really is (I love trying to break stuff!).

The process is similar to what we did earlier. We need to add a process to the “renderField” pipeline section of the web.config like this…

<processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel" />
<processor type="YourAssemblyHere.Pipelines.FieldRender.FallbackLanguageProcessor, YourAssemblyHere" />

<processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel" />

And add another class that handles this process like so…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sitecore.Pipelines.RenderField;


namespace YourAssemblyHere.Pipelines.FieldRender
{
public class FallbackLanguageProcessor
{
public void Process(RenderFieldArgs args)
{
//only perform this logic if this is not the default language
if (Sitecore.Context.Language.Name != "en")
{
if (args.Item != null)
{
//Get the current Item passed in by the arguments
Sitecore.Data.Items.Item currentItem = args.Item;
if (currentItem != null)
{
if (currentItem.Fields[args.FieldName] != null)
{
//if the current item has no valid value
if (currentItem.Fields[args.FieldName].Value.Equals("$name") ||
(currentItem.Fields[args.FieldName].Value.Equals(string.Empty)))
{
//Determine the fallback language for this item. in this case, we are forcing english.
Sitecore.Globalization.Language language = Sitecore.Globalization.Language.Parse("en");
//get the item in the default language
Sitecore.Data.Items.Item newItem = Sitecore.Context.Database.GetItem(currentItem.ID, language);


if (newItem != null)
{
//only make the update if the english field has a value
if (newItem.Fields[args.FieldName] != null)
if (!string.IsNullOrEmpty(newItem.Fields[args.FieldName].Value))
args.Result.FirstPart = newItem.Fields[args.FieldName].Value;
//disable web edit for this field, since it’s a fallback field editors should not be able to edit
args.DisableWebEditContentEditing = true;
}
}
}
}
}
}
}
}
}

Seems easy enough! Now, like before, our process will tick off and check to see if the FIELD that is trying to be displayed exist in Bangladeshi, and if not, go get the English value for that field and display that instead. Quick note: if you are accustomed to using sc:fld(‘Title’,.) in your xslt renderings, then those values don’t go through the fieldRender pipeline. You must use sc:field(‘Title’,.) in order for our custom process to have any effect. This specific issue causes grey hair apparently, so take heed! Just make sure your outputting your xslt value-of’s with sc:field. If you are using <sc:text, etc, then it should work fine.

Now, we have our FIELDS displaying English if the Bangladeshi field doesn’t have a value (this is mostly due to lazy or “too-busy-to-get-to-it” content editors ). So, here is where we currently are at. We are on the Bangladeshi site, looking at the About Us page. The top navigation is displaying either English or Bangladeshi links, depending on if that value exists in Sitecore, and all is good in the world.

“What about non-“fieldRender” pipeline values that are grabbed programmatically?” you say. Alright, let’s explore that. One example of why it is important to be able to get a fallback for a specific field programmatically is when you are setting the text property of a label to a field of an item.

So, pretend that on the Page_Load method we set a <asp: Label’s “Text” property to the Title field of the current item. We have to check to see if the item exists in Bangladeshi first, and if it doesn’t, then get the English version of the item and then display the title. Here is how to do that.

public static bool HasContextLanguage(Item item)
{
Item latestVersion = item.Versions.GetLatestVersion();
return ((latestVersion != null) && (latestVersion.Versions.Count > 0));
}

As you can see, pass it the item you want to check and it will return a “true” if the item exist within Bangladeshi (assuming you are within the Bangladeshi context), and “false” if it does not. You will use this method to see if you need to perform some additional logic, like grabbing an English version of the item and displaying the Title. Your Page_Load method might look a little something like this….

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Item currentItem = Sitecore.Context.CurrentItem;
if (!HasContextLanguage(currentItem))
currentItem = currentItem.Versions.GetLatestVersion(Sitecore.Globalization.Language.Parse("en"));
lblTitle.Text = currentItem.Fields["Title"].Value;
}
}

The last thing I want to go over is quite a bit more complex that what has been covered so far, so I apologize in advance for the mass confusion you are about to read and my general lack of ability to convey something in a more precise manner. It has to do with a fallback field on a fallback item that is a referenced target item of the current item. All that alludes to is how we handle globalization on referenced items within Sitecore (lookup fields, reference fields, multi-select fields, etc).

For example, imagine you have a “Page” Template with a lookup field called “Contact”. This “Contact” field will reference an item based on a “Contact” template that has the following fields: Name, Title, Company, Phone Number, and Address. Assume that the page and the contact are already created within Sitecore, but only in English. Along comes the Bangladeshi content editor and they add a Bangladeshi version to the page. While entering in content for the page, they select the English-only contact (we will call him “Bob” for now) and publish the item. We have to take a few things into consideration when trying to output Bob’s information.

When someone goes to the page and is in the Bangladeshi context, how do we display Bob correctly? Normally you get the TargetItem of the Contact field and display the name. In this case, it’s not so simple. You have to remember that Bob doesn’t exist within the Bangladeshi context. So first we have to get the Target item, and then do our check to see if it (Bob) exists in the current context and if not, get the English version of Bob to display. Here is how we would go about that:

Sitecore.Data.Fields.LookupField lookupField = item.Fields["Contact"];
if (lookupField != null && lookupField.TargetItem != null)
{
Item targetItem = lookupField.TargetItem;
if (!HasContextLanguage(targetItem))
targetItem = targetItem.Versions.GetLatestVersion(Sitecore.Globalization.Language.Parse("en"));
//Do Stuff with Bob here....
}

This logic is getting the “Contact” lookup field, getting its “TargetItem”(Bob), checking to see if the TargetItem exist within the current context, and if not, re-getting the target item as the English version, and then displaying the information as necessary.

I hope this all makes sense, I know I babble on and on and on and on a ….err, heh. Oh, and even after typing it 18,976 times, I still like the word “Bangladeshi”. Congratulations, you are at the end of my ranting and can go on with your lives. I hope you have learned something of value. Happy globalization!

Thanks – Caleb Miller.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/tackling-fallback-fields-and-values-in-sitecore

Tuesday, August 03, 2010

What does Sitecore v6.3 Really Mean?

So it used to be called the TwinPeaks release if you follow the Sitecore Roadmap but exactly what does it bring to the table? There are some blogs already out regarding the release. Alex Shyba showed how easy it is to cluster the CMS client (in fact he did 6 virtual servers in less than hour – follow him on Twitter to get more updates). Oh yes, that’s what v6.3 really allows you to do (plus some other stuff that you should read on the release notes). But as a business person, you might ask, so what?

Well, we know that enterprises (that’s the keyword) always need performance as one of the top requirements to be fast and efficient. The Sitecore delivery engine (i.e. content delivery – CD servers) had always been keen to being clustered and allows you to load-balance them to achieve a pretty good performance. And that’s important because Sitecore itself may use up to 30% of CPU utilization (that’s what I’ve heard a while back in v5). So making sure that the site visitors are experiencing beautiful user interactions while delivering them promptly can be a tough achievement if you don’t load-balance your delivery servers. Almost all implementations nowadays have this requirement and should now be something that you should be aware of.

Sitecore v6.3 brings a new level performance except it’s not on the delivery side of things but more on the authoring side. With v6.3, IT can now load-balance the CMS client allowing for better responsiveness. It introduces the Event Queue which Adam Conn of Sitecore blogged about (it even has a nice video). Essentially, it is like a recipe whereby if you want to replicate your mom’s cooking again and again, you follow the recipe. In a way, v6.3 CMS client servers look at the queue to see what else need to be done and thus become “in synch” with the other servers.

As a business person, should I care about this? I say yes because now there’s more freedom on how Sitecore is deployed geographically. For international companies, this makes maintaining Web site more effective. Also, this becomes an ammunition to having a more globalized management of Web sites. Sitecore had been an eye-candy for managing globalized content because of translations, languages, publishing capabilities; but, there’s always that feeling that it’s really hard to distribute authorship because of geographical distances. With v6.3, this fear or concern is minimized because performance (and reliability) becomes less of an issue.

I’m hoping that corporations will now feel comfortable bringing in your international sites into one platform, that is Sitecore. The only thing that I think that you need to be cautious is how those other systems going to integrate with your Web site and allow them to be “load-balanceable” as well. I’ll leave you with this but one hint is to consider Sitecore not just a CMS but also as a foundational technical platform for other capabilities.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/what-does-sitecore-v63-really-mean

Monday, August 02, 2010

Sorting Sitecore Items in .NET

Have you ever asked yourself what’s the fastest (or easiest) way to sort a list of item that you retrieve using SelectItems or something similar? It’s been answered before and there’s even been sample code provided before. Here are some of the ones I’ve seen:

  • using IComparer
  • brute-force approach
  • using the “sortorder” provided by Sitecore

I think the last two is self-explanatory but the first one is something that I’ve seen before on SDN and works really well. You can see a sample code on:

http://sdn.sitecore.net/Articles/API/Get%20Items%20Children%20Sorted.aspx

This solution is a definite .NET way of doing it. I would actually say old-school but effective. It uses the Sort method and passing it a custom IComparer. Just a simple Title sort would at least be 3-5 lines of code.

Although with the new C# 2.0 syntax, you can reduce the # of lines by using anonymous methods such as:

numbers.Sort((x,y) => Int32.Parse(x).CompareTo(Int32.Parse(y)));

Now comes C# 3.0’s support for LINQ, you can now use that technique to do a one-line code…yes ONE LINE!!!

The code is:

var sortedList = (from entry in unsortedItems orderby entry.Fields[“Title”].Value ascending select entry);

where unsortedItems is an array of Items (i.e. Item[]) or an ItemList or any type of collection for that matter.

So how does it work? If you’ve done LINQ (or even SQL statements) before, this should be familiar but if not, it’s quite easy. The code above grabs an Item from the unsortedItems into a variable called entry. Using the entry’s Fields property and the proper field name, I sort it using either “ascending” or “descending” keyword. The “select entry” essentially completes the statement to store that same entry into the resulting variable "sortedList”.

I’ve used this technique with other field types as well and works very well. Of course, you may need to revert back to using IComparer if you have more complex comparison rules.

CAUTION

FYI for algorithm folks, there has been mention that the LINQ’s OrderBy sort is O(n*log(n)) compared to IEnumerable’s O(n*n) which according to some is about 5 times slower with a large sample. Here’s a link you can get a more detailed analysis of OrderBy and Sort.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/sorting-sitecore-items-in-net