Веб-разработка и интернет-реклама без воды.

Позднее Ctrl + ↑

VPN: Подключаемся к Telegram в обход РКН

Заблокировали Телегу, а в ней столько контактов по работе. Ну какого русского мужика можно этим испугать? Мы законов то не особо боимся. Что ж, погнали на VPN:


Простой и безгеморройный вариант:


  1. Заходим вот сюда
  2. Скачиваем и устанавливаем программулину
  3. Подключаемся к VPN и радуемся жизни
  4. Программулина платная, от 350 рублей в месяц (оптом дешевле)

P.S. Промокод NEXTLIMITED даст +10% к оплаченному сроку действия


Геморройный вариант с рекламой:


  1. Заходим вот сюда
  2. Скачиваем и устанавливаем программулину
  3. Запускаем программу и жмём Connect
  4. Программа бесплатная, но есть незначительные ограничения
16 апреля   telegram   vpn

Simpla: Показываем JivoSite в определённое время

Сделал на одном сайте привязку кнопок «Обратный звонок» и «Отправить заявку» к JivoSite.
Возможно для кого-то это покажется дикостью, но это на самом деле удобно — обратный звонок должен происходить моментально, а не через три часа, когда менеджер по продажам, который отсиживает жопу на зарплате, накурится сигарет и напьется кофе. И JivoSite в этом плане оказался очень удобен.

Но столкнулся с интересной проблемой. В JivoSite есть настройки времени, когда можно совершать звонок с сайта. Чтобы появилась форма обратного звонка нужно нажать на соответствующую кнопку/ссылку. Конкретный пример:

Предположим мы поставим в настройках JivoSite часы работы с 9 до 18 часов. Как вы думаете, что произойдет, если мы нажмём на ссылку «Обратный звонок» в 18:02? Правильно. Ничего. Она не сработает, а это проёбаный лид. Техподдержке передал, но нужно сохранить лид уже сегодня и своими силами.

Чтобы лид остался с нами, нужно проверить сколько сейчас на часах и предложить альтернативу, например, оффлайн форму того же JivoSite. И в SimplaCMS это решалось так:

<a href="tel:{$settings->company_phone|escape}"><h3>{$settings->company_phone|escape}</h3></a>
{if $smarty.now|date_format:'%H.%M' > '09.00' && $smarty.now|date_format:'%H.%M' < '18.00' }
{literal}<a href="#" onclick="jivo_api.open({start : 'call'});">Обратный звонок</a>{/literal}
{else}
<a href="#" onclick="jivo_api.open();">Обратный звонок</a>
{/if}

Если время сервера попадает в заданный интервал, показать ссылку №1. В противном случае №2.

10 апреля   jivosite   simplacms

JS: Вешаем события GA через DOM для плагина Wordpress Contact Form 7

После опыта с LP Generator, нашёл такое же решение для самого популярного плагина Wordpress Contact Form 7. Согласно официальной документации плагина, начиная с версии 7.5.0 они убрали возможность установки событий onsubmit и onclick через интерфейс админки. И предлагают вешать его через скрипт. Пример:

<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
    yaCounterXXXXXX.reachGoal('ORDER'); gtag('event', 'order', { 'event_category': 'ORDER', 'event_action': 'ORDER', });
}, false );
</script>

Зачем убрали — не понятно, но точно ясно, что усложнили жизнь новичкам.

4 апреля   js   wordpress

JS: Цели Яндекс Метрики в LP Generator

В этом конструкторе всё сделано как то через жопу, даже настройка целей Метрики. Например, чтобы повесить onSubmit цель, которую на обычном сайте/шаблоне можно повесить в 2-3 действия, в LP Generator нужно повесить на каждую форму вот такой скрипт, который предлагает сам LP Generator:

<script>
    jq_144('#block-new2').on('submit', '.our_form', function() {
        // block-new2 - id формы
        var form = jq_144(this);
 
        jq_144('#lp_form_target').on('load', function() {
 
                if (!window.frames.lp_form_target.data_json ||
                    (window.frames.lp_form_target.data_json.length == 0)) {
                    yaCounterID.reachGoal('ORDER');
                    // ЗАМЕНИТЬ ИДСЧЕТЧИКА - на номер вашего счетчика
                    // ЗАМЕНИТЬ ORDER - на идентификатор вашей цели
                }
 
                timerName255 = setInterval(function(){
                    // ЗАМЕНИТЬ 255 на id формы
                    if (jq_144('#form_submit_message').css('display') == 'block') {
                        clearInterval(timerName255); // ЗАМЕНИТЬ 255 на id формы
                    }
                }, 100);
        });
    });
 </script>

Принцип — скрипт выбирает блок и привязывает к форме указанного блока цель Метрики. Ну что за рукожопство?

28 марта   lpgenerator   метрика

Интерфейсы: Beget vs. Hetzner

Не буду говорить о красоте. Это субъективно. Но удобство — штука важная.
Где найти информацию про DNS сервера у немцев я не сразу догадался.

28 марта   интерфейсы

Лечим Obfuscated.Globals.5.4

В последнее время прилетает много заявок на лечение сайтов от вирусов. Распространенным из них стал Obfuscated.Globals. Что ж, погнали.

P.S. Вылечу весь сайт за 2500 рублей. Пишите на a@chudenkov.ru

  1. Для начала соберем список всех зараженных файлов с помощью скрипта антивируса AI-Bolit. Скачать можно здесь
  2. Загружаем на хостинг, запускаем сканирование. Если сайт большой, можете сходить в магазин и взять пивка. Процесс долгий. Можно воспользоваться SSH и выполнить проверку за 5 минут.
  3. Получаем отчёт о заражённых файлах. В первую очередь смотрим php файлы.

  1. Открываем зараженные файлы и ищем в самом начале PHP-файла что-то подобное:

  1. Удаляем этот кусок PHP кода от <? до ?>

  1. Проходимся по всем файлам и чистим файлы от «злого» кода.
  1. Для контроля результата можно запустить AI-Bolit ещё раз.
26 марта   вирусы

Вторая цена в Simpla CMS

На базе Simpla CMS делаю каталог объектов. Возникла необходимость вывести две цены, например, за час и за смену. Реализация:

  1. Делаем SQL запрос в таблицу s_variants:
ALTER TABLE `s_variants` ADD `price2` TEXT NOT NULL AFTER `price`;
  1. Обновим запрос в /api/Variants.php в двух местах:
$query = $this->db->placehold("SELECT v.id, v.product_id , v.price, v.price2, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment, v.position
...
  1. Чтобы вторая цена выводилась в админке в общем списке товаров, добавим в /simpla/design/default/products.tpl ~80 строка:
<input class="price" type="text" name="price2[{$variant->id}]" value="{$variant->price2}" />{$currency->sign}
  1. Чтобы можно было редактировать цену в карточке объекта, добавим ~585 строчка:
<li class="variant_price">     <input name="variants[price2][]"         type="text"   value="{$variant->price2|escape}" /></li>
  1. Чтобы вывести в фронтэнде:
{if $v->price2 > 0}{$v->price2|convert} {$currency->sign}

Готово.

26 марта   simplacms

Про display: inline-block в CSS

Копипаста:

Если не установить свойство width, блоки примут по умолчанию значение ширины всей страницы и от свойства display не будет ни какого толку. Важно понимать что элементы встанут в одну линию если для них обоих (или более) будет задано свойство display: inline-block при этом между ними не будет других элементов, с отличным от данного, свойством. Если попробуем изменить класс для блока .child находящегося по середине, тем самым убрав все стили, то увидим что все элементы выстроились в ряд.

Чтобы inline-block заработал, нужно обязательно указать размеры блока. Хотя бы один из размеров.

.parent {
width: 100%;
height: auto;
}
.child {
width: 33%;
}
24 марта   css

Из ч/б в цвет при наведении на изображение

С введением CSS3 и HTML5 стал реже пользоваться jQuery, да и скриптами вообще. Например, заказчик попросил внедрить на его сайте функцию раскрашивания изображения при наведении. Для этого загрузим цветные изображения на сайт и применим для них фильтр grascale.

А чтобы всё это раскрашивалось постепенно добавим transition, в противном случае это выглядит менее эстетично.

.your-img-class {
    filter: grayscale(90%);
    transition: 1s;
}

.your-img-class:hover {
	filter: grayscale(0%);
	transition: 1s;
}
24 марта   css

Выгрузка данных формы в Битрикс-24 (JSON)

Делаем выгрузку лидов из формы прямо в Битрикс-24.

  1. Регистрируем входящий Вебхук в Битрикс-24.
  2. Записываем код авторизации (AUTH CODE)
  3. Добавим форму и обработчик.
<? 
$defaults = array('first_name' => '', 'last_name' => '', 'phone' => '', 'email' => ''); 
if (array_key_exists('saved', $_REQUEST)) { 
$defaults = $_REQUEST; 
$queryUrl = 'https://restapi.bitrix24.ru/rest/1/AUTH_CODE/crm.lead.add.json'; 
$queryData = http_build_query(array( 'fields' => 
	array( 
		"TITLE" => $_REQUEST['first_name'].' '.$_REQUEST['last_name'], 
		"NAME" => $_REQUEST['first_name'], 
		"LAST_NAME" => $_REQUEST['last_name'], 
		"STATUS_ID" => "NEW", "OPENED" => "Y", 
		"ASSIGNED_BY_ID" => 1, 
		"PHONE" => array(
			array(
				"VALUE" => $_REQUEST['phone'], 
				"VALUE_TYPE" => "WORK" 
			)
		), 
		"EMAIL" => array(
			array(
				"VALUE" => $_REQUEST['email'], 
				"VALUE_TYPE" => "WORK" 
			)
		), 
	), 
	'params' => array("REGISTER_SONET_EVENT" => "Y") ));

$curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_POST => 1, CURLOPT_HEADER => 0, CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => $queryUrl, CURLOPT_POSTFIELDS => $queryData, ));
$result = curl_exec($curl); 
curl_close($curl); 

$result = json_decode($result, 1); 
if (array_key_exists('error', $result)) echo "Ошибка при сохранении лида: ".$result['error_description'].""; 
} ?> 

<form method="post" action=""> 
	Имя: <input type="text" name="first_name" size="15" value="<?=$defaults['first_name']?>"><br/> 
	Фамилия: <input type="text" name="last_name" size="15" value="<?=$defaults['last_name']?>"><br/> 
	Телефон: <input type="phone" name="phone" value="<?=$defaults['phone']?>">
	E-mail: <input type="email" name="email" value="<?=$defaults['email']?>"><br/> 

	<input type="hidden" name="saved" value="yes"> <input type="submit" value="Отправить"> 
</form>
  1. Проверим поступление данных в Битрикс-24.
24 марта   json   битрикс
Ранее Ctrl + ↓