How to decode the ei parameter in Google search

Kevin Jones, 23rd December 2013

We’ve recently found out how to decode the ei parameter (in Google search URLs).

Or rather, we’ve simply noticed some patterns, which are extremely similar to the gclid parameter, which we wrote about a couple of weeks ago.

How is an ei value encoded?

An ei value seems to consist of:

  • 4 bytes, in little-endian order, which correspond to a 32-bit unsigned integer
  • 3 “varints”, again corresponding to unsigned integers

Finally, the resulting (binary) value is encoded in (a version of) Base64.

So, there’s no encryption.  (For me that was a surprise, because I assumed the e in “ei” stood for “encrypted”.)  I suppose that means the information is (considered by Google to be) rather boring!

It’s basically as if it were encoded in Protocol Buffers, but with the keys stripped out.

So what's actually in the ei value?

Well, there are 4 numbers.
For example, the ei tci4UszSJeLN7Ab9xYD4CQ contains:

  Array
  (
    [0] => 1387841717
    [1] => 616780
    [2] => 14362338
    [3] => 2667586301
  )

Parameter 1

The first parameter is clearly a Unix timestamp—and corresponds to the time when the search results were served.

So this particular ei value corresponds to an advert that was clicked on on 23rd December 2013 at 23.35.17.

Parameter 2

Guessing from the structure of the gclid parameter (which is extremely similar)—and the fact that this always seems to be 6 digits (or under)—we conjecture that this is the microseconds associated with the timestamp.

Parameters 3 and 4

As with the parameters inside a gclid code, we don’t know what the last two parameters mean, but we’ve noticed that the final, 4th parameter is “more” random than the 3rd.

Is this information useful?

Probably not.  It tells you the time of the search, but 99.9% of the time you’ll know that anyway (as accurately as you need).

How to decode an ei value

We've made a PHP function so you can decode ei values yourself:

function ei_decode($ei)
{
    // Copyright 2013 Deed Poll Office Ltd, UK <https://deedpolloffice.com>
    // Licensed under Apache Licence v2.0 <http://apache.org/licenses/LICENSE-2.0>
    $ei = base64_decode(str_replace(array('_', '-'), array('+', '/'), $ei));
    if (!preg_match('/^
        (.{4})
        ((?:[\x80-\xff]*[\0-\x7f])+)
        $/sx', $ei, $matches)) return false; // Non-valid ei value
    $ret = array();
    $val = 0;
    foreach (str_split($matches[1]) as $i => $c)
        $val = PHP_INT_SIZE < 5 && function_exists('bcadd') ?
            bcadd($val, bcmul(ord($c), bcpow(2, $i * 8))) :
            $val + (ord($c) << $i * 8);
    $ret[0] = $val;
    preg_match_all('/[\x80-\xff]*[\0-\x7f]/', $matches[2], $matches, PREG_SET_ORDER);
    foreach ($matches as $j => $match) {
        $val = 0;
        foreach (str_split($match[0]) as $i => $c)
            $val = PHP_INT_SIZE < 8 && function_exists('bcadd') ?
                bcadd($val, bcmul(ord($c) & 0x7f, bcpow(2, $i * 7))) :
                $val + ((ord($c) & 0x7f) << $i * 7);
        $ret[$j + 1] = $val;
    }
    return $ret;
}

Example of use:

print_r(ei_decode('tci4UszSJeLN7Ab9xYD4CQ'));

// Prints:
//
// Array
// (
//     [0] => 1387841717
//     [1] => 616780
//     [2] => 14362338
//     [3] => 2667586301
// )
//

Comments

comments powered by Disqus