Blog

Couple of Things (Smashing Magazine and Google Analytics)


"The lack of money is the root of all evil".
- Mark Twain 
 
Haven't blogged in a while. Will two halves of a piece of news make a full blog post?  let's see.
 
Smashing Magazine
SmashingMagazine, a very highly regarded website for web developers and web designers, has published an article from yours truely.
The takeway point of the article is that, once all is said and done, Responsive Web Deisgn is cool, but server-side detection can provide the extra gears to bring your site to the next level. Judging from the comments so far, it seems that I and Steve (who helped a lot with the actual example) managed to drive the point home:

Here it comes: Providing the Best User-Experience Possible. Enjoy.

The second thing that is worth mentioning on this blog today is that Google has introduced a paid Premium Analytics offering. If you are OK with the basic features of Google Analitycs we all know, analytics is free. Alternatively, if you want more, be ready to fork out $150k. 

Google Analytics Premium

Yes, that's not one hundred and fifty dollars. It's a steep 150,000.00 (one hundred and fifty thousand) dollars per year. That's a lot of money. Yet, I see this as positive news. Those systems take money to build and manage, and it is time that we come to terms again with the fact that not everything can be free of charge, not even on the Internets.

Have a good one.

Luca

You are not a man until...(WURFL InFuze and Raspberry PI)

"A man is not old until regrets take the place of dreams."

Pretty much everyone must have heard several instances of the "you are not a man until..." sentence followed by some more or less moronic action. When it comes to C APIs, I suspect that the programming counterpart recently has become "You did not build a real C API until you can compile and run it on a Raspberry PI". In fact, there seems to be a race to run every bit of software ever conceived on a Raspberry PI. So, it didn't take much before someone in our C and C++ engineering team in Milan, Italy, picked up the gauntlet and accepted the challenge on behalf of our WURFL InFuze product line.

Today, we can report that that challenge was succesfully won.

 We used a Model B Raspberry PI (512 Mb RAM and ARM 700Mhz processor). Arguably, the most popular Linux distribution for that device is Raspbian, a Debian 6 port for the ARM processor. 

We used the documentation and build scripts that are used for our standard Ubuntu and Debian 6 distributions. After installing the dependencies for compiling the WURFL InFuze products, we launched the make_all_deb_rpm.sh, script. This is the script that we run to compile all libraries and modules. Here is what the script does:

  1. Install all applications and libraries needed to compile (libboost, gcc, etc.)
  2. download the source code of the various components to include the WURFL libraries and modules.
  3. run configure and make all to compile everything
  4. launches fpm to create a .deb package.
The compilation was successful at the first attempt, exactly as we would expect for the compilation of a normal distribution of Debian 6.
 
Two packages (libwurfl.deb and mod_wurfl.deb, the Apache Module) were installed with:
 
#dpkg-i libwurfl.deb
 
Apache 2.2 was already installed by default. All the we had to do was to edit the wurfl.conf file to activate the recognition of certain capabilities, restart  Apache and... Bingo!
 
WURFL InFuze (Apache) on RaspberryPI
 
Of course, we were also able to compile the InFuze NGINX module without problems.
 
The Moral of the Story is: WURFL InFuze is now a man!
 
Enjoy!
 
The ScientiaMobile Engineering Team in Milan
 

 

WURFL and Responsive Web Design (RWD)

 

Pretend for a moment that you’re working as a front-end developer.
(If you’re already a front-end developer, well, pretend you’re

also wearing a pirate hat.)
- Ethan Marcotte, Responsive Web Design, page 17

 

 


If you have never heard of Responsive Web Design, I respectfully wonder how in the world you landed on this blog. In a nutshell, RWD has changed (and arguably, has changed single-handedly) how people create regular and mobile websites. Up to two or three years ago, building a website that worked on mobile devices necessarily involved serving a mobile-specific experience to those devices. More often than not, this included some form of multi-serving with the help of WURFL or some other server-side device detection. Today, if your targets are smartphones, RWD has changed that to a large extent.

Let me describe what RWD is briefly. RWD is the smart use of media queries and flexible grids to have a website automatically re-format itself on smaller screens, i.e. tablets and smartphones. The picture below will trigger the intuition for the intuitive reader (others can read the excellent "Implementing Responsive Design"; by Tim Kadlec).

RWD


Thanks to RWD, things have somewhat changed. Nowadays, the majority of the people who want to access the web on the go are endowed with large-screen smartphones. This has made RWD a relatively inexpensive way to create sites that adapt themselves to smartphones and developers have rushed to it. To summarize, RWD fixes the problem of how to serve mobile devices for a lot of people.

Now that you have heard of RWD, you are probably wondering what the WURFL team’s stance is in regards to RWD. As I just wrote, RWD is cheap and it does the job in most cases. Period. Straight and easy.

Follow up question: Does this mean that you don’t need WURFL to create mobile sites anymore? The answer to this is not so easy. It depends. It depends on how well you want to support the long tails of mobile devices out there and how much you want to control and optimize the user experience of your mobile users, including those with smartphones and tablets.  

The question then becomes: "How do I decide if I need WURFL or not?".

There are a few heuristics. You should start by asking yourself a few questions. "Is my website still too bloated for mobile devices?", "Is 'it sort of works' good enough for my company or do we need to do better than that?" or even “If a user of my site complains about their mobile experience, am I comfortable telling them that it is their problem and not ours?”. If the answers to those questions is that you can live (and make your mobile users live) with a sub-optimal mobile user experiencethen you probably don’t need WURFL. On the other hand, if you do want more control over your web offering, then you need a tool to control the mobile UX at levels that RWD can hardly provide. WURFL is likely to be part of the solution in that case.

Follow up question: Does this mean that one needs to choose between either RWD or WURFL? Answer, not at all! It is totally possible to combine an RWD approach with server-side components and get the best of both worlds. The acronym for this is RESS, which stands for REsponsive web design and Server-Side components (not exactly the most straightforward acronym, but hey, I am in no position to point fingers here. I am still carrying the responsibility for inventing W.U.R.FL., which is considered hard to pronounce even in Poland). The ScientiaMobile team went one step further and adopted RESS for our new website at http://www.scientiamobile.com . Our new site is RWD, with server-side optimizations made possible by our own WURFL Cloud (our dogfood actually tastes good). If you don’t believe us, visit our site with an older device and you will see what we mean (hint: capability page is multiserved, certain fringes are not provided to mobile devices and navigation menu is multiserved to older less capable devices that cannot handle DOM manipulations and touch events satisfactorily).

Follow up question: if this approach is so powerful, why hasn’t the industry created products and tools to leverage RESS in easy ways? easy answer here. Check out http://www.whateverweb.com  from the good guys at Mobiletech.

 

Luca Passani
CTO @ScientiaMobile

PS: We will be in Barcelona for MWC 2013. If you are a WURFL user and would like to meet us, shoot us an email at mwc2013@scientiamobile.com

 

Dealing with the WURFL Manager Object in ASP.NET


It is with great pleasure that we host a new contribution from our WURFL Developer Evangelist for Microsoft Technologies,  Dino Esposito.
-Luca Passani, CTO @ScientiaMobile
 

Dealing with the WURFL Manager Object in ASP.NET

WURFL is a cross-platform API available for a variety of platforms and languages. Any programmatic access to the data that WURFL holds passes through the WURFL manager object. In the end, using the WURFL API is quite easy; more interestingly, it requires the same approach and development pattern regardless of the language and platform you’re using. Programming with WURFL can be summarized in two steps:

  • Get a reference to the WURFL manager object
  • Ask the WURFL manager object for the capabilities associated with a given user agent string

Behind these two simple steps, however, there’s a whole bunch of tricks and caveats to avoid. The key point to understand is the lifetime of the WURFL manager object, its caching strategy and the impact it may have on the available memory. This post analyzes the behavior of the WURFL manager object in ASP.NET and under IIS.

What Happens on Application Startup

The WURFL library is a Device Description Repository tool (DDR) and works by serving device-specific data to requestors. The core of the library therefore is the companion database where over 500 capabilities for over 18,000 devices are stored. Once loaded in memory, this information takes up approximately 50 megabytes of space—not too much for a real-world application, but not even a little amount that can let some memory leaks pass unnoticed.

The WURFL database is not made of live data. Moreover, the data that the WURFL library holds doesn’t even change frequently. If you licensed the classic WURFL API, you have access to weekly builds of the database. If you licensed the WURFL Cloud API, you are guaranteed to have always fresh data available. In both cases, the frequency of updates is in the order of days. In summary, the WURFL data can be considered static data at least from the perspective of a web application.

This data is ideal for one-time caching at the start of the application.

In an ASP.NET application, the Application_Start method on the global.asax class is the first place where a developer can gain control over the application. If any action needs be taken before the first request comes in, well, that’s the place. The initialization of the WURFL library, and the loading of the database, will take place in Application_Start. Here’s the code that creates an instance of the WURFL manager object.

var manager = WURFLManagerBuilder.Build(new ApplicationConfigurer());

I guess that to a .NET audience, the use of the Builder pattern to just instantiate a class may seem a bit awkward. I could probably agree given the overall simplicity of the process that builds up a WURFL manager. On the other hand, just the use of the Builder pattern here is a sign of the cross-platform nature of the API.

The builder requires a configurer object. The role of the configurer is providing enough information to the builder to locate the database files. In particular, the ApplicationConfigurer class—part of the WURFL library—reads the path of the database files from a section in the web.config file.

  <wurfl mode="Accuracy">
    <mainFile path="~/App_Data/wurfl-latest.zip" />
  </wurfl>

If you would like to pass the path to the database file programmatically, you then use the InMemoryConfigurer object, as below:

var manager = WURFLManagerBuilder.Build(
                      new InMemoryConfigurer()
                             .MainFile(...)
                             .SetMatchMode(MatchMode.Accuracy));

The WURFL manager builder does just main thing: it locates the WURFL database and loads its content into a memory data structure. The WURFL database is essentially an XML file. The process of loading consists in reading the entire document and parsing it out to proper bits and pieces.

The memory data structure that ends up containing parsed WURFL data acts as an internal cache privately owned by the WURFL manager. This data structure takes up most of the run time memory required by WURFL.

In the end, once you hold an instance to the WURFL manager you hold both the actual WURFL data and tool to read them. WURFL data should be considered global in the context of an ASP.NET application.

Now the question is: how can I reference the single instance of the WURFL manager being created at startup from any other places within my application?

The WURFL Manager is a Singleton

Internally, the WURFL Manager is built like a singleton. The instance of the WURFL manager class created (and then returned) by the builder is assigned to a public static member of the builder class named Instance. In the end, in global.asax you just call the builder:

WURFLManagerBuilder.Build(new ApplicationConfigurer());

Next, in any other place where you need to make a WURFL query you use the code below:

var deviceInfo = WURFLManagerBuilder.Instance.GetDeviceForRequest(userAgent);

In alternative, you can just save the reference to the WURFL manager you get from the builder to your own singleton and use it throughout the application. For example, suppose you declare the following member on your HttpApplication global.asax class (named MyApp in the sample):

public class MyApp : HttpApplication {
   public static IWURFLManager WurflManager;
   :
   protected void Application_Start()
   {
      :
      WurflManager = WURFLManagerBuilder.Build(new ApplicationConfigurer());
   }
}

Next, you can reference the WURFL manager like below:

var deviceInfo = MyApp.WurflManager.GetDeviceForRequest(userAgent, mode);    

In this way, you are guaranteed to read always from the same piece of memory and no duplication whatsoever occurs.

Can the WURFL Manager Be Null?

The WURFL manager is never reset internally. If you correctly initialize it at the start of the application there’s no way for the manager to become null. Except, of course, that your code has a path where the manager variable is assigned a potentially null reference.

What about ASP.NET and Caching?

The WURFL manager holds its own private cache for obvious performance reasons. You can measure that the startup of the WURFL library usually takes a few seconds (only once when Application_Start is invoked) but each request is served is a matter of milliseconds. The WURFL internal cache uses a LRU algorithm and automatically retrieves device information that may have been discarded.

With WURFL, it is preferable not to use the ASP.NET Cache. The WURFL manager object exists to make static data available; by design this data is guaranteed to be available since the start of the application. Put down in .NET terms, the WURFL manager is not explicitly disposable.

You may think that storing the WURFL manager reference to the ASP.NET Cache would keep your application lean-and-mean even more. If you do so, however, you should consider a couple of possible issues. First, at some point the manager object may be removed from the ASP.NET cache. There are several possible reasons why a cached item may be discarded: memory pressure is one, but it could also be that you linked the cached item to an expiration policy (sliding time, absolute time, timestamp of files, changes in other cached items). If the WURFL manager is in the ASP.NET Cache, however, you should check it for nullness before you use it. If it’s null, you have to re-initialize it passing from the builder. At this point, though, another large chunk of memory is taken up with no guarantee that the previous chunk has been already discarded. This may lead the application pool that hosts the site to collapse. In the end, the worst that can happen is that your application recycles meaning that the entire ASP.NET Cache is cleared up as well as with any global data, session, and so forth.

When you store the WURFL manager in the ASP.NET Cache, you actually store a memory pointer and retrieve it like this:

var manager = Cache["…"] as IWURFLManager;
if (manager == null) {
    manager = WURFLManagerBuilder.Build(new ApplicationConfigurer());
}

The reference is removed from cache and left to the garbage collector but the memory it was referencing—the 50MB of in-memory WURFL data—may still be there perhaps doubled by the second manager reference you build.

Consider that ASP.NET uses strict arithmetic to determine if the application is under pressure. If your application is close to the threshold then a second allocation of 50 MB may be lethal. So 50 MB may not be a huge amount in general, but it is big enough to be the straw that breaks the camel’s back.

Updating the WURFL Database

As mentioned, as a WURFL user you have your chance to update the database on a weekly basis. Just replacing the database file on your server may not be enough. Because the WURFL data is cached on application startup, a new copy of the database is not detected automatically. While this may change in a future release of the .NET API, for the time being you should restart the web application in order for the new database to be effectively reloaded. Here are a couple of tricks to make the restart of the application happen automatically when you copy a newer database file. First, you can just place the WURFL database file under the Bin folder. By design any change detected in the tree rooted in Bin causes the application to restart. Second, you can add a line to the web.config file to track the date in which the database was installed. Also editing the web.config file, in fact, causes the application to restart. Upon restart, you have fresh data up and running.

Summary

The server machine configuration doesn’t impact much the use of WURFL either. Because the WURFL data is read once in the application lifetime and then just read there’s no issue if threads cross their way. Likewise, if you are in a Web farm scenario then each server ends up having its own copy of the same data as soon as the local copy of the application is started—simple and effective.

The bottom line is that centralizing the WURFL initialization in Application_Start and referencing the WURFL manager via a singleton—your own singleton or the built-in singleton—is the best and safest way to use the library. Enjoy!

- Dino

 

The Source Code for the article can be found here: http://www.scientiamobile.com/download/WurflExplorer.zip

Using the WURFL API with Microsoft WebPages for Mobile Device Detection

 

Dear WURFL User, it is with great pleasure that I announce that Dino Esposito, Dino for friends, is now officially our WURFL Developer Evangelist for Microsoft Technologies.
If you are a Microsoft programmer, it is very unlikely that you don't know who Dino is (hint: the guy has authored more books on Microsoft related technologies than the whole Encyclopedia Britannica).
Since we started our ScientiaMobile adventure, we were delighted to see Dino follow the evolution of WURFL and even write about it in books and articles. Over the months, this natural chemistry has evolved and we have agreed to make our mutual feelings blossom into a fully-fledged role for Dino within ScientiaMobile.
Dino is kicking off his new role by authoring this blog post about the use of the WURFL .NET API within WebPages.
This is awesome, Dino! We are honored to have you on board!
 
-Luca Passani, CTO @ScientiaMobile
 

Using the WURFL API with Microsoft Web Pages

A lightweight alternative to ASP.NET MVC, Web Pages is the underlying platform for creating ASP.NET-based web sites outside of Visual Studio. Some parts of the Web Pages infrastructure are also shared with ASP.NET MVC—specifically the Razor view engine—but for the most part Web Pages is born to be the runtime engine behind WebMatrix—an alternate and totally free IDE for authoring ASP.NET sites. The difference between WebMatrix and Visual Studio is not limited to costs. As you may know, Visual Studio also has a free version—Visual Studio Express. Visual Studio Express, however, is simply the shrink wrapped version of the full-blown Visual Studio and offers the same development experience of its bigger brothers; WebMatrix instead offers a different programming experience and extensively relies on ad hoc components and widgets. Overall writing a Web site using Web Pages results in a different type of experience when compared to using ASP.NET Web Forms or ASP.NET MVC.

In this article, I’ll show you how to integrate the WURFL ASP.NET API in a web site developed using the Web Pages infrastructure and authored using WebMatrix in lieu of Visual Studio. I am also assuming that you are already all set with binaries and that both WebMatrix and Web Pages are correctly installed on your machine. If not, you can visit  http://www.asp.net/web-pages and  follow the (few) instructions listed to get started.

WURFL for ASP.NET

Once you have opened up WebMatrix and arranged a new blank project, the first thing you do is bringing up the Nuget window and add the WURFL package to the project. The Nuget setup adds some entries to the web.config file and binds a couple of executables to the project. It also downloads the most recent publicly available chunk of the WURFL database.

Take some time to review the license agreement WURFL comes with; essentially, you are free to use WURFL in open-source projects, but you may need to acquire a license from ScientiaMobile for any commercial use. Once you get a subscription, you gain access to database updates on a weekly basis. This ensures that you are always up-to-date with fixes and new devices as they hit the market.

Tweaking the web.config

The Nuget package setup adds a couple of lines to web.config. One adjustment being made regards the working mode of the WURFL library. In particular, you find the following:

<wurfl mode="Performance">
   <mainFile path="~/App_Data/wurfl-latest.zip" />
</wurfl>

The ZIP file is the database to replace once you’ve got a subscription; what you get by default is the latest public snapshot of the WURFL database at the time the Nuget package was released. Nothing here is set in stone, meaning that you can move the ZIP file to any location on the web server that you like and you can also freely rename the file. The WURFL library recognizes the database as plain XML file or compressed as a ZIP or GZIP file.  

The mode attribute indicates the expected behavior of the library as far as device detection is concerned. The default value of Performance indicates that performance is privileged; however, you can trade performance for accuracy as well.

<wurfl mode="Accuracy">
   <mainFile path="~/App_Data/wurfl-latest.zip" />
</wurfl>

For mobile devices, you won’t notice any difference; for devices that happen to be desktop computers the Performance mode takes a shortcut and always identifies the user agent as a generic web browser. In other words, in Performance mode you won’t be able to distinguish say Internet Explorer 9 from Google Chrome or any version of Firefox. However, you always get full information about tablets or smartphones.

Adding global.asax

WURFL needs some bootstrapping code to be run only once per application start. To achieve this in ASP.NET, you might want to add a global.asax file to the project. In WebMatrix, you right-click to add a new file to the project, switch to the All view and then pick up the ASAX file for the language of choice. (See Figure 1.)

 

Ensure the global.asax file contains the following:

<%@ Application Language="C#" %>
<%@ Import Namespace="WURFL" %>
<%@ Import Namespace="WURFL.Aspnet.Extensions.Config" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        RegisterWurfl();
    }
    public static void RegisterWurfl()
    {
        MyApp.WurflContainer = WURFLManagerBuilder.Build(new ApplicationConfigurer());
    }
</script>

 

The WURFLManager.Build method uses a newly created instance of the ApplicationConfigurer class to detect the location of the database and then parses the content into memory. The returned object—known as the WURFL container—holds a cache of the WURFL data. You need to make this object global throughout the application so that you can query it for device details on every subsequent request. A good option is assigning the WURFL container object to a public static property of a global application object. For this reason, you add the App_Code folder to the project and create a new file in it named MyApp. (Note that the name MyApp is arbitrary.) Here’s the code for the MyApp.cshtml file:

@using WURFL;
@functions{
    public static IWURFLManager WurflContainer;
} 

At this point, you are entitled to invoke MyApp.WurflContainer from every page in your application.

Querying for Device Capabilities

A Web Pages web site is a collection of pages written using the Razor syntax and saved to a CSHTML files. The pattern of using WURFL can be summarized as below:

1)      You run a query against the WURFL database using the user agent string as the key; you receive back from the library an object of type IDeviceInfo;

2)      You use the methods on the IDeviceInfo interface to know about specific capabilities of devices associated with the given user agent string;

3)      Based on the detected capabilities you intelligently serve ad hoc markup to the requesting browser.

In the sample project, I have just one page—default.cshtml—that is expected to perform a sort of a x-ray diagnostic exam on your browser. Here’s the code that queries WURFL about the operating system of the device:

@{
    // Grab WURFL info for a given UA
    var deviceInfo = MyApp.WurflContainer.GetDeviceForRequest(Request.UserAgent); 
    // Query for some capabilities
    var cap_OperatingSystem = String.Format("{0} {1}",
              deviceInfo.GetCapability("device_os"),
              deviceInfo.GetCapability("device_os_version"));
}

WURFL provides over 400 capabilities for several thousands of different mobile devices, including tablets, smartphones, legacy phones, smart TVs, console boxes and regular desktop PCs. Full reference about supported capabilities can be found at http://www.scientiamobile.com/wurflCapability/tree. Any of the strings you documented at the URL can be passed to the GetCapability method.

Note that as of the current API (version 1.4.3.1) the GetCapability method always returns a string. In a future version, though, we plan to add a few extension methods that return strongly typed values for easier programming in both WebMatrix and Visual Studio.

Making Use of WURFL Data

Using WURFL in web sites means essentially two, non-exclusive things:

1)      You use WURFL to know the class of the device, whether it is a tablet, a smartphone or perhaps a smart TV. Next, armed with this knowledge you route the request to different class-specific views;

2)      You use WURFL to know about specific capabilities which take you to enable or disable certain features you expect to have in the page. For example, if the browser doesn’t support video streaming you may want to render some friendly messages or if the browser doesn’t support, say, RSTP streaming you might want to configure the streaming widget to use an ad hoc URL.

Once you know how to access the IDeviceInfo object for a given user agent string, you’ll almost done. All that remains to do is just rendering the page in the most appropriate way. Figure 2 shows the sample application in action. It takes a snapshot of the current device and renders it out. The sample application is available online for testing at http://www.expoware.org/wurfl

A link to the source code for a WebMatrix project is available below.

http://www.scientiamobile.com/download/Wurfl_WebPages.zip

Porting the code to ASP.NET MVC is trivially easy and … left as an exercise to the reader J

 

Perl and WURFL: There is only one way to do it right


I read everything: fiction, history, science,

mathematics, biography, travel.

Perl (Martin Lewis Perl)

 
 
November 5, 2012, IMPORTANT UPDATE:  Perl Cloud Clients now Available in CPAN too!
 
 
I learned Perl in 1994, before Perl 5 was created, while still at the University. It was the reference language for everyone who wanted to do web development before 1996. I loved Perl. It was powerful. You could do in one day what would easily take weeks to do with other languages at the time. And this still applies today to a large extent. The difference today is that a lot of other powerful scripting languages have come about and taken the best from Perl, while avoiding its mistakes (no matter if real or perceived).

I think it is reasonable to state that Perl is the way it is because it boldly dared to go where others had not dared. All other scripting languages capitalized on Perl’s experience in some way.
Of course, I learned the hard way that one is walking on thin ice when discussing Perl in public. Things get religious and the discussion gets heated quickly. Proficient Perl programmers can be super-productive. No doubt about that. On top of that, Perl one-liners have made my day multiple times.
On the other hand, there is truth to the fact that Perl lends itself to be a “write-only language”, particularly if you don’t use it that often and you adopt snippets found on the web that you don’t fully grasp in the first place (but that fix your problem there and then). If you are interested in the discussion about the pros and cons of Perl, StackOverflow has this great post.

WURFL Cloud Client for Perl
The main driver behind the decision to support Perl, is that a fair amount of organizations still use Perl out there. There is no standard standalone WURFL API for Perl. There are a few third-party scripts and modules that read the WURFL file, but, as you may suspect, none of those implements the logic that the standard API from ScientiaMobile implements. And that’s what one really needs to make WURFL express its potential.

From today, Perl developers have access to the latest and greatest WURFL through the Perl Cloud Client, also available from CPAN. As usual, this includes the free offering for hobbyists and small companies. Launching the Perl Cloud Client  makes business sense, but it also feels good for me and Steve. It’s like we paid a tribute to a language that gave us a lot in the past.

Enjoy

Luca Passani
CTO @ScientiaMobile

 

HTTP and Mobile: The Missing Header

 
“Everything you always wanted to know
 about your HTTP Clients, but were afraid to ask.”
 

I cannot count the times I heard someone wonder why on earth device manufacturers never added an HTTP header that would make it obvious that an HTTP request is coming from a mobile device. I typically had witty answers to that question. ‘The header existed. It was called UAProf. Apple killed it’. 

Jokes aside, the answer to that question lies in the economics of the whole thing: mobile stakeholders do not agree on who is entitled to decide what content and what user-experience should be delivered to users, hence the inability to agree on a standard and stick by it.

The point we are making today is not why such a header does not exist, but rather that the ScientiaMobile team is finally launching products that will make that header (and a limitless array of other WURFL-powered headers) available to WURFL adopters.   Today we have made the beta version of a set of modules for Apache, NGNIX and Varnish-Cache (all based on our WURFL C++ API) available to commercial customers. This opens a whole range of new possibilities.

Let me proceed, with order. As you know, installing WURFL and managing a WURFL installation takes a certain amount of work and dedication. This is particularly demanding in the case of large organizations, dealing with several data feeds, content repositories, CMSes and geographically dispersed teams. Wouldn’t it be awesome if the HTTP spec already came with headers such as x-wurfl-is-wireless-device, x-wurfl-is-tablet and x-wurfl-ux-full-desktop to indicate the true nature of each device, tablet or desktop browser? This would allow companies to leverage device information within the very frameworks, tools and programming languages they use today.

Thanks to the products that we make available in their beta form today, this is now a reality. In the case of Varnish-Cache, for example, the VCL configuration would look something like:

sub vcl_init {
    wurfl.set_root("/usr/share/wurfl/wurfl.xml");
    wurfl.add_patch("/usr/share/wurfl/wurfl_patch.xml");
    wurfl.set_engine_target_high_performance();
    wurfl.set_cache_provider_double_lru(10000,3000);
 
    wurfl.add_requested_capability("brand_name");
    wurfl.add_requested_capability("model_name");
    wurfl.add_requested_capability("marketing_name");
    wurfl.add_requested_capability("device_os");
    wurfl.add_requested_capability("device_os_version");
    wurfl.add_requested_capability("is_tablet");
    wurfl.add_requested_capability("is_wireless_device");
 
    wurfl.load();
    if (wurfl.error()) {
        panic wurfl.error();
    }
}
 
sub vcl_recv {
 
    set req.http.X-Wurfl-Id = wurfl.get_device_id();
    set req.http.X-Wurfl-RootId = wurfl.get_root_id();
    set req.http.X-Wurfl-IsDevRoot = wurfl.is_actual_device_root();
    set req.http.X-Wurfl-Cap-Brand-Name = wurfl.get_capability("brand_name");
    set req.http.X-Wurfl-Cap-Device-Os = wurfl.get_capability("device_os");
    set req.http.X-Wurfl-Cap-Device-Os-Version = wurfl.get_capability("device_os_version");
    set req.http.X-Wurfl-Cap-Is-Tablet = wurfl.get_capability("is_tablet");
    set req.http.X-Wurfl-Cap-Is-Wireless-Device = wurfl.get_capability("is_wireless_device");
 
    if (wurfl.error()) {
        std.syslog(wurfl.error());
    }
}
 
As a little, but interesting aside, it appears that using "X-" as a way to declare experimental headers is no longer recommended.
On the other hand, it is way too early to talk about standardization, I think that the 'X-' format still makes sense.
 
Let’s look at the HTTP request from a Nokia Lumia 900 the moment it passed through Varnish-Cache, enroute to the web server (Apache in our example):
 
WireShark Snoop of Varnish Traffic
 
The implication of this is that PHP, Java, .NET programmers and virtually any other programmer on the planet can access the power of WURFL with the simplicity of:
 
// PHP
if ($_SERVER['HTTP_X_WURFL_IS_TABLET'] == ‘true’) {
       //Do whatever makes sense for a tablet
}
 
I guess Apache would be another good example, albeit the reader may object that there is no point in using Apache when you already have Varnish. To this, I counter-object that there is no limit to the technlogy anti-patterns tucked away inside multi-layered large organizations. smiley
 
// You can even use it in an Apache rewrite condition
RewriteCond %{HTTP:x-wurfl-is-tablet}   =TRUE
RewriteRule ^phone/(.+)$ tablet/$1
 
The example above referred to Varnish, whose natural job is being a reverse-proxy. But also NGINX and Apache can be set up as reverse proxies. We could show you the same example with NGINX, or show you the configuration of NGINX for a different use-case. For example, we could use NGINX to enrich our environment variables ($_ENV[]) with capability values, effectively making those capabilities available in the most natural way for a variety of uses.
 
Enriching the Environment Variables
NGINX can be compiled with the WURFL Module and configured as follows:
 
http {
    ...
    
    #wurfl root definition (one per config)
    wurfl_root      /usr/share/wurfl/wurfl.xml;
    
    #wurfl patch definition
    wurfl_patch     /path/to/patch1.xml;
 
 
    wurfl_target_performance;
 
    wurfl_cache_double_lru 10000,3000;
 
    # specify all required capabilities
    wurfl_request_capability brand_name;
    wurfl_request_capability model_name;
    wurfl_request_capability is_wireless_device;
    wurfl_request_capability is_tablet;
    wurfl_request_capability ux_full_desktop;
    
    ... 
    server {
        ...
 
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
            include        fastcgi_params;
 
            # Example to inject Wurfl Capabilities to FastCGI Environments
            fastcgi_param WURFL_ID $wurfl_id;
            fastcgi_param WURFL_BRAND_NAME $wurfl_cap_brand_name;
            fastcgi_param WURFL_MODEL_NAME $wurfl_cap_model_name;
            fastcgi_param WURFL_IS_WURELESS_DEVICE $wurfl_cap_is_wireless_device;
            fastcgi_param WURFL_IS_TABLET $wurfl_cap_is_tablet;
            fastcgi_param WURFL_UX_FULL_DESKTOP $wurfl_cap_ux_full_desktop;
        }
        ...
    }
}
 
 
Which, in turn, would allow PHP programmers to do things like:
 
if ($_ENV['WURFL_IS_TABLET'] == 'true') {
       //Do whatever makes sense for a tablet
}
 
Of course Perl, Python and everything that can run in a CGI environment can take advantage of the same functionality.
 
Other uses of the Varnish-Cache, Apache and NGINX Modules
Enriching the HTTP request or the Environment Variables with new headers and values are obvious use cases. This allows organizations to “inject” the value of WURFL without disrupting (or even without redeploying) existing sites and systems. This lowers the burden on application developers and removes the need to maintain a WURFL library dependency in their code base.
 
But these are not the only use cases that the WURFL Modules enable. Other uses are possible.  For example, URL rewriting or routing can be made mobile-aware to preserve URL 'uniformity' for end users (i.e. make sure that the same URL leads to the same content but with different user-experiences for mobile users). 
Adopting separated caching strategies for mobile and desktop clients is another totally sustainable option. Once WURFL is built-in into your network, the possibilities are endless.
 
 
Enterprise
The C++ API and modules are meant for enterprise customers. Because of this, they are not distributed under a dual licensing model like other WURFL APIs. Distribution of the C++-based products only happens under commercial terms.
 
Beta Phase
The NGINX, Apache and Varnish-Cache modules are the result of several months of development and testing. In spite of this, we realize how sensitive a spot WURFL is going to occupy once deployed at the network level. For this reason, ScientiaMobile has chosen to go through a beta-phase before general availability. If your company is interested, you can contact us through this form and we will work with you to deploy the module and make sure that it works satisfactorily for you. 
 
Early adopters will be rewarded.  You can quote me on that.
 
Luca Passani
CTO @ScientiaMobile
 
PS: ScientiaMobile, Inc. is not affiliated in any way with the Apache Software Foundation, NGNIX Software Inc., RedPill Linpro AS or Varnish Software AB. 
 

 

BDConf and Exposing WURFL Capabilities to JavaScript

Simplicity is the ultimate sophistication
- Leonardo Da Vinci (disputed)

Steve and I were at the awesome Breaking Development Conference  last week in Dallas, Texas. What an amazing stand-up of great speakers (and what an amazing chance for networking!).

The presentations covered quite a lot of ground and a variety of topics. Some speakers gave their more high-level “long term” visions of where mobile is going and how every device (including your toaster) will be communicating with whatever else (but not through Bluetooth). I found those talks interesting, but also, I find those speakers very brave: how can they go out on a limb and say those things with no fear that someone will actually verify if their prophecies actually came true one day?
As a quick aside, about one month ago, all of Norway was laughing about a 1996 article that stated how the Internet was a complete flop and divined that it would never conquer a place in more than 1% of the households. For the record, Leif Osvold, the author, subsequently has admitted that he was wrong.

Jokes apart, I loved the other face of the BDConf even more. That’s the speakers who share real hands-on experience on how to build mobile sites and overcome the challenges of the kind that they encountered along the way. La creme de la creme of mobile web bloggers and professionals can be found at BDConf and the audience listen to them religiously. Not surprising. Content is king and those guys (and girls) are the high priests of total sense-ness.

It was the first time at BDConf for me. What I recalled from reports of previous editions was a lot of attention to Responsive Web Design. This was of course still the case, but Server-Side Detection has been added again into the diet of mobile web developers: I did not hear anyone disagree that RWD/Mobile-First (client-side) and Device Detection (server-side) are both useful tools in the arsenal of mobile developers. At the end of the day, it is a matter of choice and developers picking what cuts it for them.

More specifically about the RWD vs Server-side discussion, Ronan Cremin was one of the speakers. Ronan works for our commercial competition, but, credit where credit is due, he went on stage with a pretty decent set of slides that made a basic point clear: people access the web on desktops, tablets, phones, TVs and their wristwatches. Input methods vary wildly: touchscreen, clickwheel, keyboard&mouse, remote control, D-PAD and who knows what else. In this contest, a responsive approach can only bring you so far.

But Ronan was not the only one to put RWD in context. Brad Frost (who wrote an awesome RWD tutorial at some point), surprised the audience with a spectacular “Users don’t give a s**t if your site is responsive” slide all by itself 
(see slide 159) . I couldn’t agree more, so I had to clap my hands, albeit in solitude.

Coincidentally, an article by Ronan Cremin and me on exactly this topic was published by Smashing Magazine during the conference days, and that article contains the same points raised by the two speakers above.

The editor of Smashing Magazine had warned me that the discussions about the merits of client-side vs. server-side can quickly get religious and very heated. I did not come across any of that religiosity at BDConf, though. But Steve observed something else. Web/Front-end developers are not always as proficient with server-side languages (such as PHP or Java) as one might assume. They are more likely to be familiar with JavaScript (in addition to HTML and CSS, of course). In this context, isn’t the discussion between RWD and WURFL a direct corollary of the old “when all you have is a hammer, every problem looks like a nail”? and of course, doesn’t this apply also the other way around, with backend developers favoring a solution to device fragmentation that leverages the tools they know best?  mmmm...food for thought...

On our way home, 20,000 feet above the earth, I was discussing with Steve about how we can do more to expose WURFL capabilities to JavaScript. Steve correctly objected that this is already possible today and has been possible since forever. After all, any developer worth their mettle knows how to use JSP, PHP, or whatever else to spit out JavaScript. This is correct. On the other hand, showing a different way to do it may be inspirational to those people who eat and breath JavaScript every day. Let us not underestimate the implicit power of <script src=”..”> to import external resources without implications on how the main HTML page is generated.

Bringing JavaScript Higher
Here is today’s problem. Let us assume that we want to know whether our page is running inside a smartphone phone (but not a tablet). Also, assuming it is a phone, we want to know what the device’s actual make, model and marketing name (if available) are. Finally, we want to capture that information inside a JavaScript object “wurfl” as properties:

is_smartphone
is_tablet
brand_name
model_name
marketing_name

These capabilities can be accessed like “wurfl.is_smartphone”.

Developers familiar with WURFL know what to do. Just embed that JavaScript generation directly into your PHP page. So we will raise the bar slightly. Let’s assume that the site is managed through some legacy CMS, and the PHP code that defines the templates cannot be modified by the front-end developer, while anything JavaScript can be. 

Mmmm...things get more interesting now.

We can create a separate PHP page, on a different web server, that  uses the WURFL API (either standalone or in its Cloud incarnation) that generates JavaScript (mime type text/javascript) and looks something like this:

------------------
<?php
require_once dirname(__FILE__).'/../Client/Client.php';

header('Content-Type: text/javascript');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');

$config = new WurflCloud_Client_Config();
$config->api_key = '879060:XK8cG1Rq6NSDLdAIsCkuPeFhVfnnDlvE';
$client = new WurflCloud_Client_Client($config, new WurflCloud_Cache_Null());
$client->detectDevice();

$capabilities = array(
'is_smartphone',
'is_tablet',
'brand_name',
'model_name',
'marketing_name',
);

$out_data = array();

foreach ($capabilities as $cap_name) {
$out_data[$cap_name] = $client->capabilities[$cap_name];
}

$json_data = json_encode($out_data);
echo "wurfl = $json_data;\n";
exit;
?>

-----------------------

When it comes to importing those JavaScript values in the page, this is as simple as:

<script src=”//server.mysite.com/talkToCloud.php”></script>

EXAMPLE HTML:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WURFL from JS Example</title>
<script src="/WurflCloudClient-PHP/temp/wurfl-js.php"></script>
</head>
<body>
<h1>WURFL Capabilities:</h1>
<ul id="capability-list"></ul>
<script>
var list = '';
for (var cap in wurfl) {
list += "<li>" + cap + ": " + wurfl[cap] + "</li>";
}
document.getElementById('capability-list').innerHTML = list;
</script>
</body>
</html>


At this point, the front-end engineer is able to use WURFL capabilities just as easily as he would use any other JavaScript variable.

A Note about the Example
The code above assumes the use of the Cloud Client and the use of the PHP programming language, but it goes without saying that the example can easily be ported to any of the standalone APIs as well as any of the other Cloud APIs (Java, .NET, Ruby, Python, Node.js and soon Perl). And of course, any WURFL capability can be exposed, not just the ones we mentioned in the example (if you have a patch file, you can expose the capabilities from your own patch file).
Cloud users should further observe that the capability they pick must be enabled in the WURFL Cloud control panel.

Conclusions
We had fun at BDconf and you can use WURFL where you may not have expected it. In case you are curious, the next BDConf will take place in Orlando, Florida, in April 2013.

Enjoy

Luca Passani, CTO @ScientiaMobile, with contributions from Steve Kamerman, COO @ScientiaMobile

 

WURFL in the Cloud with Node.js

 

"JavaScript was my first love, but will it be my last?
in this world of trouble, we put Node.js to the test."
 
 
 
I started my professional career as a web programmer. I learned HTML and Perl for CGI scripts while at my last year in college and the only browser was Mosaic. I was excited when Netscape came about and even more so when they introduced some client-side interactivity through LiveScript, soon to be renamed JavaScript (I guess someone in some large company's marketing department had decided that exploiting the Java wave was a good idea).
 
JavaScript accompanied me in the first years of my professional career. The fact that I had understood how HTML layers worked on both MSIE 4 and Netscape 4, made me an invaluable resource for my employer. I would wipe out a few hundreds JavaScript lines that Dreamweaver had automatically generated for my colleagues, and replace them with a few lines that exploited 'eval()' to make themselves cross-browser at runtime. Bingo.
 
Then came WAP, and there was no need for me to look at JavaScript again for some time. wink
 
When I decided to look at JavaScript closely again a few years later, quite a few things had changed.
 
jQuery had delivered a brand new way to look at a page, its events and its DOM. Netscape 4 (and MSIE 4, 5 and 6) were a memory of the past. Apparently, things had changed a lot also on the language side. 
I looked at those scripts and, honestly, I could not make sense of them. Way too many things had changed.
 
Thanks heaven I found a good book that put me back on track (a high-level track, but nevertheless...):
 
 
This is a book that I warmly recommend, but brace for things like:
 
"Because JavaScript is a functional object-oriented language, functions can have methods"
 
As it turns out, JavaScript has become (maybe it always was, I simply never realized) a very elaborate and powerful language. This, along with the release of an Open-Source JavaScript engine by Google, made it merely a question of time before JavaScript became an attractive (and credible way) way to do server-side development (I will mention JScript on first generation Microsoft ASP only to demonstrate that, at the time, I was there already). 
 
Node.js was born and it is growing progressively popular, as the impressive line of corporate adopters demonstrates.
 
The ScientiaMobile team can clearly see the value that Node.js delivers and, today, we are proud to announce the addition of a Node.js Cloud Client to the arsenal of tool we offer to our customers.
 
As usual, the Node.js client can be applied to our free Cloud Offering too. Developers who want to play around with the new Node.js client can register on our site and sign up for free Cloud Usage
 
Enjoy
 
Luca Passani
CTO @ScientiaMobile
 

 

New WURFL Public Snapshot Available

ScientiaMobile has released a new public snapshot (2.3.2) of the WURFL data file.  The snapshot can be downloaded at wurfl.sourceforge.net.

WURFL Cloud and standalone API customers have access to weekly snapshots of the WURFL data, as well as out-of-band snapshots that are released when major updates have been made mid-week.