loading...
Cover image for How we reached react devs among our users

How we reached react devs among our users

aziaziazi profile image Camille Gabrieli Updated on ・3 min read

tldr: devtools globals variables let you guess if your user has a React debugger installed

Last year my team was striving to find React developers to join us and happily translate fancy product team ideas into JavaScript. With a few million happy users per week, some of our users may be a good fit for our team! Did they know we hire? Probably not! Our career page was accessible by a tiny link between press and affiliation at the bottom of the unlogged home page. And indeed our product was so captivating that they were probably too busy using the app to think about career aspirations! Still we didn't want show a career message to everyone as it would be irrelevant for most of them.

🧑‍💻 Method

While performing delightful debugging session, Nicolas and myself came with this idea: as React devtools plugin exposes a global variable, we can use it to know if a user has installed it and toggle a message !

When the page loads, the devtools sets a global named __REACT_DEVTOOLS_GLOBAL_HOOK__, then React communicates with that hook during initialization.

Easy ! Let's try it:

// code/hello-react-dev.js

if (!!window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
  console.log('Hello React Dev!');
}

We can also detect any other dev plugin that exposes some variables. We came with __REDUX_DEVTOOLS_EXTENSION__ and __VUE_DEVTOOLS_GLOBAL_HOOK__, let me know if you know more!

We also need a way to close the message and persist the information to avoid displaying it again. Let's wrap this in a component:

// code/dev-message.jsx

import React from 'react';
import { useCookies } from 'react-cookie';

export const DevMessage = () => {
  // Store if user has already closed the message
  const [cookies, setCookie] = useCookies();
  const cookieName = 'hasClosedDevMessage';
  const hasClosedDevMessage = cookies[cookieName] === 'true';
  const handleClose = () => setCookie(cookieName, true);

  // Check what plugins are installed
  const userPluginNames = [
    ['react', !!window.__REACT_DEVTOOLS_GLOBAL_HOOK__],
    ['redux', !!window.__REDUX_DEVTOOLS_EXTENSION__],
    ['vue', !!window.__VUE_DEVTOOLS_GLOBAL_HOOK__],
  ]
    .filter(([name, value]) => value)
    .map(([name]) => name)
    .join(', ');

  // Only display the message if user has a plugins installed
  // and if s.he didn't close the message yet
  if (hasClosedDevMessage) return 'reset your cookies to see the message';
  if (!userPluginNames) return 'install a plugin to see the message';
  return [
    <h1>Hello {userPluginNames} Dev !</h1>,
    <a href="https://youtu.be/dQw4w9WgXcQ" target="_blank">
      interested ?
    </a>,
    <button onClick={handleClose}>no thanks</button>,
  ];
};

And that's it ! You can try it live here

live exemple screenshot

🕵️ Others techniques

With React, Redux and Vue plugins we target a precise but narrow field of developers. Others methods may be inspired by fingerprinting techniques :

  • Detect available fonts used by developer: if you have FiraCode or Jetbrains Mono installed on your machine, there's a good chance it's for your IDE!

  • Uber "Code on the Road" seems to only use you location to propose you a test during you ride.

  • Google uses it's own data -your search history- to propose you to pass the foo.bar challenge.

  • You may look for for Github, Stack Overflow, docs references... in the navigation history. Not sure if that's legal or not, I wouldn't recommend you to do that.

  • Last but not least: console.log messages. I like the fact that it's logged for everyone but only the curious will see it.

🕶️ Privacy concern

As long as the cookie is anonymous and stays on the user machine it seems fine: looking for someone's global variables is quite similar to approaching him/her in the street to compliment his/her cool webpack t-shirt.

🥳 Did it work ?

Kind of: with around 1.5 click/day the exposure seems sufficient to keep the experiment going. And we did receive a candidacy from it!

The approach I shared here with you is fairly simple. However I think it's always nice to think about new original ways to take advantage of the tools we use every day. Hope it gave you some inspiration!

Posted on by:

aziaziazi profile

Camille Gabrieli

@aziaziazi

Front end dev passionate about component and cheese

Discussion

pic
Editor guide