Device Detection with the User-Agent

Device Detection with the User-Agent

Have you ever wanted to implement a feature for a specific platform or device? Like show a screen or some content to mobile users only or execute a different an action based on the user's device

I usually come across contents on sites that are clearly meant for mobile users only while I browse on desktop.

The User-Agent can be helpful in this scenario.

MDN defines the user agent as

The User-Agent request header is a characteristic string that lets servers and network peers identify the application, operating system, vendor, and/or version of the requesting user agent.

A common format for a user agent string looks like:

Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>

Detect User's device

To know if a user is on mobile you need to look for "Mobi" in the user agent string as you can see in the example below

const BUTTON = document.querySelector("button");

const { userAgent } = window.navigator;

// Set device to "mobile" if "Mobi" exists in userAgent else set device to "desktop"
const device = userAgent.includes("Mobi") ? "mobile 📱" : "desktop 💻";

BUTTON.addEventListener("click", () => alert(`You are on ${device}`));

The example above result in desktop example Desktop Demo

mobile example Mobile Demo

Test in your browser

To test this in your browser, open the developer tools and click on the 'toggle device' icon. Refresh your page for changes to apply

Practical Example

Here is a practical example of this in my React application.
I used this in a federated login

// Context API for device
import { createContext, useEffect, useState } from "react";

export type TDevice = "mobile" | "desktop";

export const DeviceContext = createContext<TDevice>("mobile");

const DeviceContextProvider: React.FC = ({ children }) => {
  const [device, setDevice] = useState<TDevice>("mobile");

  useEffect(() => {
    const { userAgent } = navigator;
    // Set device state
    userAgent.includes("Mobi") ? setDevice("mobile") : setDevice("desktop");
  }, []);

  return (
    <DeviceContext.Provider value={device}>{children}</DeviceContext.Provider>
  );
};

export default DeviceContextProvider;
// login with provider hook
const useLoginWithProvider = (redirect: (path: string) => void) => {
  const device = useContext(DeviceContext);
  const [signInAttempt, setSignInAttempt] = useState(false);

  const login = async (provider: string) => {
    if (device === "mobile") { // Check if user is mobile
      firebase.auth().signInWithRedirect(providers[provider]);
      setSignInAttempt(true);
    } else {
      firebase
        .auth()
        .signInWithPopup(providers[provider])
        .then(handleResult)
        .catch(error => setError(error.message));
    }
  };

  useEffect(() => {
    if (signInAttempt) {
      firebase
        .auth()
        .getRedirectResult()
        .then(handleResult)
        .catch(error => setError(error.message));
    }
  }, []);

  return login;
};

export default useLoginWithProvider;

Conclusion

Obviously, you can tell this is not meant to replace media queries, however, this can be very useful in your projects. Media Queries are mainly used for responsive pages whereas this method is for device-specific features or content. This is mainly useful when you want your mobile app to behave differently from the desktop version. You can use this to give mobile users app-like experience especially when dealing with Progressive Web Apps

Read more from MDN docs

Photo by Daniel Korpai on Unsplash