Correctly Form User-Agents for Webview Apps

Correctly Form User-Agents for Webview Apps

User-Agents for WebviewHybrid webview apps are a popular and cost efficient way to distribute online properties through app stores. A hybrid app is a native application with all the bells and whistles, but some part and sometimes even all functionality is developed using HTML, CSS ,and JavaScript and rendered by a webview component. This is why the hybrid app is also called a “webview app”. You can think of the webview component inside the app as a browser window. Inside the browser window, a webpage or web app is rendered. This page or app is communicating with a server on the internet, just like a web browser. We know how important the User-Agent string is for device detection in web browsing, and correctly formed User-Agents for Webview Apps is just as important for effective browsing, analytics, and targeting.

This article will teach you how to steer away from the generic defaults and correctly form a meaningful User-Agent for hybrid webview apps on mobile devices running the most popular platforms. If your app does not use webviews , then please read this post to learn how to structure User-Agents for native mobile apps.

Importance of User-Agents for Webview Apps

The User-Agent is a header field in the HTTP request. Its purpose is to identify the the program or application making a request for web content. The User-Agent “is often used by servers to help identify the scope of reported interoperability problems, to work around or tailor responses to avoid particular user agent limitations, and for analytics regarding browser or operating system use”, according to the specification.

In a hybrid webview app context, enabling the webpage or app displayed inside the webview to adapt navigation or presentation to the different browsing experience is very useful. Especially when the webpage integrates with functionality natively built into the hybrid app.

From an analytics perspective, it is crucial to know where the traffic of the hybrid app is coming from and which app versions on which devices are generating the traffic. This is not obvious using the defaults provided by the SDK.

The motivation for meaningful User-Agents in hybrid apps is much the same as for native apps, but with User-Agents in hybrid apps they carry app information, device information, plus the standard browser information. 

Adding information to the User-Agent in hybrid apps is already common. Most of the popular apps like Facebook, Twitter, and Instagram already do follow these User-Agent guidelines.

Composing the User-Agent for Webview Apps

How should the User-Agent be formed? In the following we’ll demonstrate how to compose the User-Agent for webview based applications. The base of the User-Agent is the default User-Agent as provided by the platforms SDK, and then app and device information is appended. This is the defacto standard as it has developed in the wild:

<Stock User-Agent> WebViewApp <AppName>/<Version>

Note the WebViewApp identifier before the app name and version.

Let’s look at how to compose the correct User-Agent for different platforms and operating systems. For this purpose, we’ll construct User-Agents for a webview app called Foo, version 1.

User-Agent for Hybrid Android apps

For our app running on a Nexus 5, this is how our User-Agent could look:

Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/32.0.0.0 Mobile Safari/537.36 WebViewApp Foo/1

The code to construct the User-Agent is:

String ua=new WebView(this).getSettings().getUserAgentString(); 
webviewToUse.getSettings().setUserAgentString(ua + “ WebViewApp Foo/1”);

User-Agent for Hybrid iOS Apps

For iOS it is slightly more complicated, but still not difficult. We still want to append app name and version, but in addition we want to append the specific iPhone model at the end:

Mozilla/5.0 (iPhone; CPU iPhone OS 6_0_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A525 WebViewApp Foo/1 iPhone4,1

Above is the User-Agent of Foo version 1 running on an iPhone 4S (iPhone4,1).  

The examples below use the deviceName() to get the model information. See github for full code examples.

Objective C

In Objective C, we retrieve the user-agent by creating a webview:

UIWebView* webView = [[UIWebView alloc] initWithFrame:CGRectZero];
NSString* ua = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];

Then we modify the extracted User-Agent via the AppDelegate file:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: ua + @" WebViewApp Foo/1 " + [self deviceName], @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

Swift

In Swift we do it like this:

let userAgent = UIWebView().stringByEvaluatingJavaScript(from: "navigator.userAgent")! + "WebViewApp Foo/1 " + getName();
UserDefaults.standard.register(defaults: ["UserAgent" : userAgent])

Windows Phone

Like for Android, we only need to append the app name and version since the device info is already in the default User-Agent.

First we extract the User-Agent by creating a webview:

public static string UserAgent;

public void LoadUserAgent() {
	string Html = @"<html><html> <head> <script language=""javascript"" type=""text/javascript""> 
                function notifyUserAgent() { window.external.notify(navigator.userAgent); } </script> </head> 
                <body onload=""notifyUserAgent();""></body> </html>
		"; 

	var tempWebBrowser = new Microsoft.Phone.Controls.WebBrowser();
	tempWebBrowser.IsScriptEnabled = true;
	tempWebBrowser.Visibility = System.Windows.Visibility.Collapsed;
	tempWebBrowser.Loaded += (sender, args) => tempWebBrowser.NavigateToString(Html);
	tempWebBrowser.ScriptNotify += (sender, args) =>
	{
		UserAgent = args.Value;
		LayoutRoot.Children.Remove(tempWebBrowser);
	};
	LayoutRoot.Children.Add(tempWebBrowser);
}

Now, append “ WebViewApp Foo/1”.

UserAgent = UserAgent + “ WebViewApp Foo/1“;

Then have the webview use your custom User-Agent:

private void webView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
    webview.Stop();
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(args.Uri.Host));
    httpRequestMessage.Headers.Append("User-Agent", “UserAgent”);
    webView.NavigateWithHttpRequestMessage(httpRequestMessage);
}

 

The Foo/1 app on a Lumia could look like this:

Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 535 Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.0.0 Mobile Safari/537.36 Edge/13.0 WebViewApp Foo/1

Conclusion

With this relatively modest effort during development, you can can gain better analytics of your apps usage patterns and adapt content and ads to their specific apps, devices, or OS.