Someone is playing your awesome new multiplayer game on mobile and wants to invite a friend to play with them. How do we make that as easy and seamless as possible? Here’s an idea I’ve been toying with…

First, let’s outline the ideal workflow, then we’ll see how to get there.

  1. Start a match and invite a friend, triggering native “share” action
  2. Send link to a friend who’s never played before
  3. Friend sees a web page with a summary of the invite and a button to install the game
  4. Friend is taken to the store where they complete the install and open the game
  5. Friend is taken directly to the match from the original invite
  6. All future invites open directly in the game and go to the desired match

Let’s break this down.

In step one, the player creates and joins a match. Regardless of the multiplayer framework it’s safe to assume there is a unique identifier for each match, game room, etc. When an invite link is generated we can include this identifier in the URL. e.g.

Step two is handled by the mobile OS. It doesn’t matter how the link is delivered to the other player.

In step three we take advantage of an existing, well-documented feature of iOS and Android called universal links. There’s plenty of guides out there describing how to set this up, so I’m skipping over that here. In a nutshell, if the user already has the app installed, the link opens in your app and it’s straightforward to read the match identifier and connect them.

The difficult scenario I want to discuss is when the other player does NOT have the app installed. If we do nothing extra, they would install the app, open it, and the data from the universal link would be lost. Now the player has hit a dead end, increasing the likelihood of frustration and drop-off.

To prevent this dead-end scenario, we’ll implement something called a “deferred deep link”. It’s “deferred” because it fires after the app install.

To do this, we need a way to remember the player who visited the invite web page in step three. This is not straightforward because Apple and Google have (rightfully) implemented extensive privacy constraints to prevent abuse. All is not lost, there are a handful of identifying attributes we can use to create a fingerprint that is good enough for our purposes. I’m calling it “good enough” because we aren’t dealing with sensitive data. In the unlikely event of a mismatch, the worst case scenario is a random person in the wrong game match or the game behaves as it would have without this trick.

Here’s the steps required to implement:

  1. Generate a fingerprint for the user when they visit the invite web page and save it to our server along with the identifier for the match they wanted to join.
  2. When a player launches the game for the first time, generate the fingerprint in the game, using the same method as on the web.
  3. Send the fingerprint to our game sever to check if it matches any previously saved records.
  4. If no record is found, don’t do anything; maybe the user didn’t previously visit an invite link.
  5. If we find a record, send the match identifier back to the client so it can automatically join the match

But how to generate this fingerprint? We can only use information that is available both on the web and in the game. Therefore, some good candidates are:

  • IP address
  • Operating system version
  • Screen resolution

We should be able to collect this info from the web page and in-game to generate a possible match. For example, the web page can use JavaScript to get the screen size and call an API to save the record. Sever-side we can collect their IP address from the HTTP request and OS version from user agent details. In-game we can generate the fingerprint the same way, using our game engine to report the screen size and OS version to the server.

To increase the odds of a successful match we can add a few more features to this system.

  • Expire records after 5-10 minutes
  • Delete records after they have been successfully matched
  • Don’t create records if any of the data is missing

This might not sound like enough details to make a reliable match, but keep in mind this is only checked the first time someone runs the game. If the fingerprints don’t match due to a breakdown somewhere along the way, no harm done. If a new player falsely matches a random invite before it is matched by the intended player, they’d be joined a game match with a random player. You’ll have to decide if this is acceptable behavior for your game. If your game is usually played between strangers anyway, this might not be an issue.

I’d love for both iOS and Android to implement an official way to preserve universal link data post-install, but until then we’ll have to use tricks like this.

Have ideas for improvement? Let me know on Twitter @playsupernormal