21

I want to be able to detect user when the user browses a web page inside twitter app. By detecting, I want to just add a body class that I will use to change the way the page looks for users inside twitter app. However, all my tries so far failed.

I can detect webview inside Facebook app using the following code

var ua = navigator.userAgent;
if ((ua.indexOf("FBAN") > -1) || (ua.indexOf("FBAV") > -1)) {
  return 'facebook';
}

I have looked around/ googled around/ checked other StackOverflow solutions. However, I could not find a solution where I can detect twitter in-app. That is, I want to detect when a user browses a page inside twitter app.

The things I have tried and failed are below

   if (/Twitter for/i.test(nua) === true) {
      return 'twitter';
   }

or

if (/\/\/t.co\//i.test(document.referrer) === true && /Safari\//.test(nua) === false) {
  return 'twitter';
}

or checking for the browser, device, vendor, model, device type, engine, os, os version (why was I checking this?!?). I checked using Modernizr; however, no difference was found between as standalone Safari and in-app Twitter. Also, checked using Detect if user is using webview for android/iOS or a regular browser

Also tried the following with failure

   var userAgent = window.navigator.userAgent.toLowerCase(),
      safari = /safari/.test( userAgent ),
      ios = /iphone|ipod|ipad/.test( userAgent );

var standalone = window.navigator.standalone,
  userAgent = window.navigator.userAgent.toLowerCase(),
  safari = /safari/.test( userAgent ),
  ios = /iphone|ipod|ipad/.test( userAgent );

if( ios ) {
  if ( safari ) {
    $('.debug').prepend('Yeah I am a browser in ios');
  } else if ( !safari ) {
    $('.debug').prepend('Yeah I am a webview in ios');
  }
} else {
  $('.debug').prepend('Yeah I am NOT a ios');
}

if( ios ) {
  if ( !standalone && safari ) {
    $('.debug').prepend('Yeah I am a browser in ios');
  } else if ( standalone && !safari ) {
    $('.debug').prepend('Yeah I am a standaline in ios');
  } else if ( !standalone && !safari ) {
    $('.debug').prepend('Yeah I am WEBVIEW');
  }
} else {
  $('.debug').prepend('Yeah I am NOT IOS');
}

var isWebView = !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone'
$('.debug').prepend('<br>isWebView? : ' + isWebView + "<br>");
$('.debug').prepend('<br>AM I WEBVIEW?: ' + /AppName\/[0-9\.]+$/.test(navigator.userAgent));

var is_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent);
var is_safari_or_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);
$('.debug').prepend('<br> is_uiwebview :' + is_uiwebview);
$('.debug').prepend('<br> is_safari_or_uiwebview :' + is_safari_or_uiwebview);


var uaSafari = navigator.userAgent.match(/Safari/i)
var uaSafariInput = navigator.userAgent.match(/Safari/i).input
var uaSafariIndex  = navigator.userAgent.match(/Safari/i).index
$('.debug').prepend('<br> ' + uaSafari + '<br>' + uaSafariInput + '<br>' + uaSafariIndex + '<br>' + navigator.vendor + '<br>' + navigator.product + '<br>' + navigator.productSub + '<br>' + navigator.languages.length + '<br>' + navigator.doNotTrack + '<br>' + navigator.maxTouchPoints + navigator.maxTouchPoints);

//Check headers and see if any difference there
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
$('.debug').prepend('<br> headers \t ' + headers);


if (/Twitter for/i.test(navigator.userAgent) === true) {
  $('.debug').prepend('<br> Test1 ');
}

$('.debug').prepend('<br> Document referrer is : '+ document.referrer + " <br> ");

if (/\/\/t.co\//i.test(document.referrer) === true && /Safari\//.test(navigator.userAgent) === false) {
  $('.debug').prepend('<br> Test2 ');
}
  }

3 Answers3

9

I don't believe it's possible to detect the Twitter in-app browser in JavaScript, because it uses a generic Web View with no identifiable properties.

Most of your examples rely on searching the user agent string for specific keywords. Here's a comparison of user agent strings between the relevant browsers in iOS 11 for iPad based on a test I just conducted:

Safari

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5372a Safari/604.1

Facebook (in-app)

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Mobile/15A5372a [FBAN/FBIOS;FBAV/140.0.0.63.89;FBBV/70896504;FBDV/iPad4,2;FBMD/iPad;FBSN/iOS;FBSV/11.0;FBSS/2;FBCR/AT&T;FBID/tablet;FBLC/en_US;FBOP/5;FBRV/0]

Twitter (in-app)

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5372a Safari/604.1

You can see that Twitter's browser user agent is identical to Safari.

Obviously this is not a solution to your problem, but more of an explanation why you haven't found an actual answer.

Jon Uleis
  • 17,693
  • 2
  • 33
  • 42
  • 1
    That is very sad to know. :( –  Oct 02 '17 at 23:01
  • 3
    Apple don't authorise other browser engines on ios. Underneath they're all based on WebKit. That's why the user agent is exactly the same between apps. The twitter and facebook apps all use the same browser engine under the hood. Maybe change strategy and see if there are url parameters specific to the app in the page context or possibly even js variables. You'll have to dig for any differences. Alternatively @SwagatoBhatta could try browser fingerprinting, though it may not be reliable enough. – Daniel Lane Oct 03 '17 at 14:02
2

You can check if navigator.mediaDevices is undefined. Since webRTC isn’t supported in webviews, it will be undefined in Twitter but present in Safari.

0

Twitter uses t.co to warp the shared URL, so there is a redirect before reaching the real content.

https://developer.twitter.com/en/docs/basics/tco

When checking all the headers sent from Twitter in-app browser, the referer header filed shows the wrapped t.co link.

referer: http://t.co/ 0JG5Mcq

Maybe this header can help distinguish with Safari's User-Agent.

Jichao
  • 1
  • 1
  • 1