Как получить 100/100 Google PageSpeed Insights и не подать виду

Один из заказчиков попросил меня немного причесать сайт, заодно прописать цели для Яндекс.Метрики и Google Analytics. Между делом он рассказал мне, что предыдущим «оптимизаторам» удалось разогнать сайт до 100 баллов в PageSpeed Insight, мол, работа по оптимизации была долгая и значение упорно не хотело расти, но однажды подскочило до 100 и на этом закончили.

Я был немного удивлен услышанным, т.к. это был сайт на Joomla на бюджетном шаред-хостинге, с косяками адаптивной версии, неоптимизированными прозрачными PNG-шками по несколько мегабайт весом. В перерыве между работой ради интереса решил замерить баллы, правда через встроенный в Google Chrome Lighthouse.

33 балла в Lighthouse, странно

Опять переспросил заказчика, он говорит что показывает 100, но через сервис на сайте PageSpeed’а. И действительно.

А теперь самое интересное. Идем в index.php в корне сайта, и смотрим. Начало файла.

<? eval(gzuncompress(base64_decode('eAGdUtEKgjAU/ZUegilEIFNBYg/6UoQQ2IsVIWv6EkFgkfj37WwZIZtKL/dcvWfn3p3d+TrdJXG6P5HCizwahEHk04KcWVzXvHUu/FGFflFW4l5WDhE0I7MlaRF4nrxEg4wx4i56TPyX7JbnyCQT0JiYqkJRlmyA1AWIhgEM2voEtDGBUVN2xmE7Q3VAUDP+r9M5MtLp1wmrZ+Na2tGhabWDuJhiITE52PPb4uLHH0D3MhbmZnsD64jgRc9Dnl15jA/rG2rfQRnYDZRxZ+AEh0GbtBNK97tf7uoN8+vb5g==')));
eval(gzuncompress(base64_decode('eAG9kt1qg0AQhV8lF4IKvdDNmlaCF0npGmkMuLqrbClh/alKtlqsJiah7974ALG9SHs3MHM+Zs6Zt65K2rKuJlvDhBBo8H6mSKV6lri1aBp+VGQfYUKQSYlG/UhDK0wMIt/JHiiOMdDFmvQfDBQat009AcS6tK4ogncK08jNN541MvVXXIKc1tN3HRGjO4ZmycNeXL/iZhxbdAzgfUyXBQM0SGwq2GLMmeAXu+GA/idjfXIOG3To3CCfRo+wH+rn8mGIl+zoJtAxurzME0bOSOIYmHsGeuGgwQmSk+lSsNDL/dA48TCt05U7ov7ZlRvx1XmTtV1TTWL+mc3gNs2SOs0Uib9I5as6//oGaeX0oA==')));

Я первым делом подумал что сайт завирусован. Однако постороннего кода нигде не было, кроме как в index.php.

Чуйка и тут не подвела. Убираю посторонние вставки и опять проверяю скорость в PageSpeed.

Теперь все стало ясно. Для интереса все же решил разобрать обфусцированный код. Первый проход можно сделать через любой сервис для деобфусцификации, например:

<?php function _594420476($i) {
    $a = Array('SFRUUF9VU0VSX0FHRU5U', 'Q2hyb21lLUxpZ2h0aG91c2U=', 'SFRUUF9VU0VSX0FHRU5U', 'TmV4dXMgNQ==', 'SFRUUF9VU0VSX0FHRU5U', 'Q2hyb21lLUxpZ2h0aG91c2U=', 'SFRUUF9VU0VSX0FHRU5U', 'TmV4dXMgNQ==', 'SFRUUF9VU0VSX0FHRU5U', 'UFItQ1kuUlU=', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'SFRUUF9VU0VSX0FHRU5U', 'UFItQ1kuUlU=', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'SFRUUF9VU0VSX0FHRU5U', 'UGluZ2RvbVBhZ2VTcGVlZA==', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'SFRUUF9VU0VSX0FHRU5U', 'UFRTVA==', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'SFRUUF9VU0VSX0FHRU5U', 'UFRTVA==', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'LzIwNFwuMTg3XC4xNFwuKi8=', 'UkVNT1RFX0FERFI=', 'SFRUUF9VU0VSX0FHRU5U', 'R29vZ2xlIFBhZ2UgU3BlZWQgSW5zaWdodHM=', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl', 'SFRUUF9VU0VSX0FHRU5U', 'R29vZ2xlIFBhZ2UgU3BlZWQgSW5zaWdodHM=', 'SFRUUF9VU0VSX0FHRU5U', 'TW9iaWxl');
    return base64_decode($a[$i]);
}
$GLOBALS['_1913565943_'] = Array(base64_decode('c3R' . 'y' . 'aXBvcw' . '=='), base64_decode('' . 'c3RyaX' . 'Bvc' . 'w=='), base64_decode('c' . '3' . 'Rya' . 'XBv' . 'cw=' . '='), base64_decode('c' . '3RyaXBvcw=='), base64_decode('c3Ry' . 'aXBvcw=='), base64_decode('' . 'c' . '3RyaXBvcw=='), base64_decode('c3Ry' . 'aXBvcw=='), base64_decode('c3R' . 'yaXBvcw=='), base64_decode('' . 'c3RyaX' . 'Bvcw' . '=='), base64_decode('c3R' . 'yaXBvcw=='), base64_decode('c3RyaXBvcw=='), base64_decode('c3Rya' . 'X' . 'Bvcw=' . '='), base64_decode('c3' . 'Rya' . 'XBvcw=='), base64_decode('c' . '3Ry' . 'a' . 'XBvcw=='), base64_decode('cHJl' . 'Z' . '19tYXRjaA' . '=' . '='), base64_decode('c3RyaXB' . 'vc' . 'w=='), base64_decode('' . 'c3Ry' . 'aXBvcw=='), base64_decode('' . 'c3Rya' . 'XBvcw=='), base64_decode('c3Ry' . 'aXBv' . 'cw=' . '='));

Уже лучше. Убираем конкатенации и пробегаемся через base64_decode.

if (stripos($_SERVER["HTTP_USER_AGENT") ], "Chrome-Lighthouse") && !stripos($_SERVER["HTTP_USER_AGENT" ], "Nexus 5")) {
    echo $p_0;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT"], "Chrome-Lighthouse") && stripos($_SERVER["HTTP_USER_AGENT" ], "Nexus 5")) {
    echo $p_1;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT" ], "PR-CY.RU") && !stripos($_SERVER["HTTP_USER_AGENT"], "Mobile")) {
    echo $p_0;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT"], "PR-CY.RU") && stripos($_SERVER["HTTP_USER_AGENT"], "Mobile")) {
    echo $p_1;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT"], "PingdomPageSpeed") && !stripos($_SERVER["HTTP_USER_AGENT" ], "Mobile")) {
    echo $p_0;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT"], "PTST") && stripos($_SERVER["HTTP_USER_AGENT" ], "Mobile")) {
    echo $p_1;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT"], "PTST") && !stripos($_SERVER["HTTP_USER_AGENT"], "Mobile""/204\.187\.14\.*/")) {
    echo $$p_0;
    die();
}
if (preg_match("REMOTE_ADDR", $_SERVER["HTTP_USER_AGENT" ])) {
    echo $p_0;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT" ], "Google Page Speed Insights") && stripos($_SERVER["HTTP_USER_AGENT" ], "Mobile")) {
    echo $p_1;
    die();
}
if (stripos($_SERVER["HTTP_USER_AGENT" ], "Google Page Speed Insights") && !stripos("HTTP_USER_AGENT" ], "Mobile")) {
    echo $p_0;
    die();
}

В коде проверяются заголовки User Agent’а: если заходит бот Google, либо PR-CY.RU, то отдаем им «упрощенную версию сайта», либо мобильную, либо десктопную — пустой HTML файл с одним изображением скриншота сайта.

В переменных $p_0 и $p_1 лежит текст с HTML-страницей примерно со следующим содержимым:

<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgo=" type="image/x-icon"> 
<title>Pagespeed</title>
<meta charset="utf-8">
<meta name="keywords" content="Pages speed">
<meta name="description" content="Pages speed">
<meta name="viewport" content="initial-scale=1, width=device-width">
</head>
<body>
<style>*{padding:0;margin:0} img{animation: fadein 1s;} @keyframes fadein { from { opacity: 0; } to { opacity: 1; }}</style>

<img src="data:image/jpeg;base64,

Полностью код с содержимым base64 изображения не выкладываю в целях конфиденциальности. Но я думаю общий смысл понятен для тех кто разбирается.

Скрипт проверяет кто заходит на сайт. Если это бот Google или PR-CY.RU, то им заместо сайта отдается скриншот сайта. Из-за небольшого объёма страницы и быстрой загрузки баллы увеличиваются до 100.

Кстати, обратите внимание на CSS в HTML. Ребята действительно «постарались» и сделали так, чтобы скриншот загружался плавно, с анимацией прозрачности. Думаю это для того, чтобы заказчики ничего не заподозрили глядя в скриншоты trace рендеринга страницы, а может такая обманка для Google. Не ясно до конца, но красиво.

Всё было бы смешно если бы не было так грустно для клиентов. Сайт вполне может попасть под блокировку за обман, а деньги за работы уже ушли.

Вот такие вот интересные IT-кадры попадаются, коллегами назвать язык не поворачивается. Полное неуважение к окружающим и к себе в первую очередь.

Глюк Firefox в Mac OS X: открытие вкладки в новом окне

Столкнулся с весьма интересной багофичей в Firefox >9.0 под Mac OS X.

При переключении вкладок иногда вкладка, по которой производится клик, перемещается в новое окно. При детальном разборе было выявлена закономерность такого поведения: при неровном клике, т.е. при малейшем смещении курсора во время клика или при удержании курсора происходит захват вкладки.

Спустя неделю мучений было решено покончить с этой проблемой, полез в гугл и отыскал решение.

Скачать можно по следующей ссылке: https://addons.mozilla.org/firefox/downloads/latest/12276/addon-12276-latest.xpi?src=userprofile

Описание на BugZilla: Bug 489729 — Clicking a tab once and then moving your mouse in a downward motion causes a new window to open.

Workaroud представляет собой дополнение с дополнительными настройками:

Настройка 12 струнной гитары

Замечательный тюнер для 12 струнной гитары на Flash от get-tuned.com, постоянно им пользуюсь для настройки своей гитарки и вам советую. Залил к себе на сайт, чтобы не потерять такую ценность, а то мало ли чего.

Еще вы можете скачать тюнер к себе на компьютер.

UPD: Для тех у кого с инетом проблемы, я выложил ZIP с настройщиком. В архиве обычный html и swf, нужно распаковать архив и запустить .html файл. Открывается в любом браузере. Требуется наличие Adobe Flashplayer.
Скачать 12stringstuner.zip (156 kb)