GeoIP and device redirects with workers

Anyone has some full working code for that to use on free CF version? I saw here are my threads about GeoIP redirects with workers but cannot understand which code can work, because there are many of them dropped in many threads.

Basically i need this: https://www.domain.com should redirect to many different URLs depending of visitors country and device(desktop/mobile).

That’s certainly going to complicate things. Geo is pretty straightforward. Mobile is much more difficult if you’re not just using Cloudflare’s Mobile redirect in Speed → Optimization. You might want see if mobile-redirect will trigger before the main site’s Worker.

1 Like

Can this be done that way:

Visitors will be separated by devices by CF Mobile redirect - https://www.domain.com and https://m.domain.com

Then setup 2 separate Country redirects for desktop/mobile in Workers.
And Add route for https://www.domain.com → desktop worker; https://m.domain.com → mobile worker.
?

Yes, it is possible, but I suggest doing only 1 redirect at the end.

Try this example instead:

const redirect = async (request) => {
 
  //cf-ipcountry and CF-Device-Type are not supported in the preview
 
  const {url: requestUrl, headers} = request
  const url = new URL(requestUrl)
  const {pathname, hostname} = url
  const country = headers.get('cf-ipcountry')
  const device = headers.get('CF-Device-Type')

  if (country != null && device != null) {
    
	let redir = false;
	
	if(device === 'mobile' && !hostname.startsWith('m.'))
	{
		hostname = `m.${hostname}`
		redir = true
	}
	if(device === 'desktop' && hostname.startsWith('m.'))
	{
		hostname = hostname.substring(2)
		redir = true
	}
	if(countryCodes.includes(country) && !pathname.startsWith('/'+ country.toLowerCase()))
	{
		hostname += '/' + country;
		redir = true
	}
		
	if(redir)
	{
		return Response.redirect(new URL(`https://${hostname}`).href)
	}
  }

	return await fetch(request)

}

const countryCodes = ['CN', 'RU', 'US']

const handleRequest = async (request) => redirect(request)

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

Note that CF-Device-Type requires an Enterprise plan.

That’s correct!

Free, Pro and Business Plans must use something like this to get the device type:

const userAgent = request.headers.get('user-agent') || ''
const device = userAgent => ([/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i].some(d => userAgent.match(d))) ? 'mobile' : 'desktop'

2 Likes