We had what I thought was an interesting issue recently while working with my team at Layer One Media on a client project. I thought it was a great story and a solution worth sharing. A mobile friendly responsive design was the main goal of this particular project, which we have a long history of delivering successfully. In this particular case, the customer was using a collection of General Link fields to control the various navigational features on their Sitecore site. However, during testing on iOS, it was discovered the telephone links that had been created were now causing the markup to break.
Upon investigation, the issue was quick and easy to identify. Sitecore was treating the General Link fields that were being used for the Telephone Link Protocol as it does any other link and adding the http protocol to the front, automatically. One developer even got creative and removed the http:// manually from the field and then hit Save. Yes, that did temporarily allow just "tel:###########" to be stored as desired in the Content Editor. However, Sitecore's renderField pipeline method GetLinkFieldValue would simply inject it again.
Next, this creative & solution oriented developer started to utilize JavaScript to clean it up. Thankfully, I was able to get involved first and prevented this from causing extra technical debt. Among my many mantras, such as "Get It Right The First Time", I also firmly believe in "Fix the issue at the Source" or at least as close to the source as feasible. I took this as a teaching opportunity. This developer had already searched Google, of course, and found the numerous excellent articles out there, notably the one Akshay wrote a while back. If you want to dive deeper into creating custom Field Types, Renderers, etc., check it out. However, this particular developer was relatively new to Sitecore and was justifiably overwhelmed at how complex it appeared.
While creating a custom field type is the ideal long term way to go, I also believe in making the least amount of changes in order to achieve a "Minimal Viable Product." So I proceeded to show him how to resolve this issue with just one real line of code injected into the appropriate Sitecore pipeline. I'll show you the "quick fix" approach, which is the simplest and most efficient.
Finally, I would like to close by drawing attention to the latest microformat open standard for hCard and h-Card (v2) formats. The business benefits of using these microformats is the fact that they provide a much wider array of compatibility across browsers and devices. The newer h-Card standard does dive into deeper requirements as they are needed for various cultures, time zones, phone number formats, etc. Additionally, microformats are universally understood by the search engines.
If you would like to see the code or implement these features on your own site keep reading…
In order to ensure that the Telephone protocol tel: remains intact when using a Sitecore General Link or Link field, we simply have to create our own custom class that follows the Sitecore Pipeline pattern of implementing a public virtual void Process(RenderFieldArgs args). In our case here is the full code:
namespace Sitecore.SharedSource.TelLinkPipeline
{
public class GetTelephoneLinkFieldValue
{
public virtual void Process(RenderFieldArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (Context.Site.DisplayMode == Sites.DisplayMode.Edit) return;
if (args == null || args.FieldTypeKey != "general link") return;
if (string.IsNullOrEmpty(args.Result.FirstPart) &&
string.IsNullOrEmpty(args.Result.LastPart)) return;
args.Result.FirstPart = args.Result.FirstPart.Replace(telToken, "tel:");
}
}
}
The one line that actually does the work is:
args.Result.FirstPart = args.Result.FirstPart.Replace("http://tel:", "tel:");
This class gets inserted into the Pipelines using a config patch file:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<renderField>
<processor type="Sitecore.SharedSource.TelLinkPipeline.GetTelephoneLinkFieldValue, Sitecore.SharedSource.TelLinkPipeline"
patch:after="processor[@type='Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel']" />
</renderField>
</pipelines>
</sitecore>
</configuration>
The main thing to notice is that our new Pipeline process actually gets patched after the OTB GetLinkFieldValue that injects the "http://" prefix/protocol.
Finally, in order to implement the hCard and h-Card microformats, you simply have to use the Style Class field and populate it with "tel" for hCard and "p-tel" for h-Card and ideally wrap the entire "contact" with <div class="vcard"> for hCard and "h-card" for h-Card.
hCard:
<div class="vcard">Whenever you are ready, you can implement the more advanced features of the microformat, such as cultures, timezones, phone number formats, by using the newer h-Card microformat and the value class pattern.