Одна из наиболее востребованных функций социальных кнопок «поделиться» — это счетчик совершенных действий. Малое число лайков и шеров может говорить* о «некачественности» материала; большие числа, наоборот, служат своего рода социальным доказательством и заставляют других делиться контентом.
В ситуации с большими числами становятся актуальны отдельные счетчики для каждой иконки-кнопки соцсети. Однако, даже простой вывод такого счетчика не всегда просто организовать — с технической и визуальной точек зрения. Проще говоря:
- счетчик может отвалиться в самый неподходящий момент;
- некоторые социальные сервисы не предоставляют данных о репостах в принципе;
- а другие не всегда в состоянии обеспечить корректную передачу этой информации.
Как разработчики собственного сервиса готовых социальных кнопок uSocial.pro мы знаем, что более половины пользователей** ставят себе отдельные счетчики для каждой кнопки. Поэтому нам было важно сделать так, чтобы цифры на счетчиках внезапно не пропадали и не врали. Готовых инструментов решения этой задачи мы не нашли, так что пришлось разработать свой — о нем мы сегодня и расскажем.
1. Что может пойти не так со счетчиками соцсетей
Казалось бы, что может быть проще — показать, сколько человек поделились контентом, лайкнули его или добавили в избранное? Для этого всего-то нужно проанализировать список установленных на сайте соцкнопок и отправить запросы к каждому из сервисов, а затем красиво вывести ответ. Но даже здесь может возникнуть ряд проблем, простого готового решения для которых нет.
1.1 Цифр просто нет
Прежде всего, счетчиков для кнопок определенной соцсети может не быть вообще — по решению самой соцсети. Например, Twitter не отдает данные о «поделившихся» по своим кнопкам. В итоге, у разных кнопочных сервисов вы могли наблюдать картину, при которой для всех соцкнопок цифры есть, а для твитнувших они отсутствуют:
Выглядит это странно.
1.2 «Они отвалились»
Соцсети гордятся высоким аптаймом, но понятно, что серверы, отвечающие за работу тех или иных сервисов, могут периодически «отваливаться». Поэтому может возникнуть неловкий момент, когда значения для нескольких кнопок могут вовремя не подгрузиться. С точки зрения восприятия — опять же, нехорошо.
1.3 «Мои глаза»
Итак, некто получил over9000 репостов во все возможные ленты. Эта информация на счетчиках должна быть аккуратной, понятной, и красивой. Но если цифры большие, их нужно сокращать — и эти сокращения могут выглядит очень странно.
Например, соцсеть G+, все значения репостов, превышающие 9999, сокращенно пишет, как >9999:
Главный российский конкурент Google, к слову, тоже не всегда безгрешен в подобных ситуациях. Например, 496 писем он может сократить до 99+. Смысл этого непонятен: информация неверная, а для ее отображения использованы те же три символа.
2. Как мы решали эти проблемы
Почти ни в одном случае нам не удалось найти «волшебную таблетку» в чужих скриптах и дизайнах. Пришлось поработать самим. Начать решили с главного — отсутствия данных по числу расшариваний для некоторых популярных соцсетей.
2.1 Расшаривания для Твиттера и ЖЖ, которых раньше не было
Если определенный ресурс не хранит статистику по шерам, либо не предоставляет к ней данные через API (как LiveJournal), то такую информацию мы храним у себя.
Для этого используется MySQL с общей таблицей, в которой хранится хэш URL и количество расшариваний в Twitter и LiveJournal. При соблюдении всех условий работы это количество просто увеличивается на единицу (инкрементируется).
Кроме того, в базе есть отдельные таблицы по каждой соцсети, в которых хранится соответствие хэша URL и поделившимися контентом пользователями. Для оптимизации производительности и чтобы не проводить дополнительных проверок, в этих таблицах присутствует уникальный индекс по двум столбцам — хэшу URL и ID пользователя. Это позволяет, помимо прочего, защититься от накруток шеров одним и тем же пользователем.
// Пытаемся создать запись о шаре
try {
$shareInsert = $share->insert([
'url' => $urlHash,
'usocial_user' => isset($content->usocialUser) ? $content->usocialUser : ""
]);
} catch (QueryException $e) {
// Ловим все ошибки, кроме ошибки, когда индекс по url и usocial_user не уникальный, т.е. данный пользователь
// уже кликал на данной странице по данной шаре.
if ($e->getCode() !== '23000') {
throw $e;
}
}
// Увеличиваем общее значение счетчика
if (isset($shareInsert) && $shareInsert) {
$curUrlShares = SharesCount::where('url', '=', $urlMd5);
// По данному URL шар не было, создаем запись
if ($curUrlShares->count() === 0) {
DB::table('shares_count')->insert([
'url' => $urlHash,
'url_original' => $url,
$content->provider => 1
]);
}
// По данному URL шары были, увеличиваем значение счетчика
else {
$curUrlShares->increment($content->provider);
}
}
В uSocial пользователи сами формируют наборы кнопок «Мне нравится» и «Поделиться» для своих сайтов, некоторые из них могут не включать кнопки Twitter и ЖЖ в набор. В таком случае мы грузим информацию только по нужным соцсетям.
А чтобы увеличить скорость загрузки, при просмотре бара с кнопками на сайте мы отображаем информацию из кэша, а не из БД — это очень положительно влияет на быстродействие.
2.2 Что делать, если ничего сделать нельзя
Но расшаривания в Twi и ЖЖ оказались семечками по сравнению с Pocket. Его разработчики отдают данные только при установки их виджета на сайт. При этом, внимание (!), отдается фрейм, в качественной работе которого не уверены даже его создатели. Вот их собственное описание:
<!-- Please do not scrape this for the Pocket count. It is not relible for you to use and will likely change. Contact us at api@getpocket.com for an official API. Thanks! -->
Мы начали договариваться о доступе к API — но ребята с той стороны после каждого ответа пропадали на месяц. Что делать?
Узнали, японский разработчик-энтузиазст под ником ktty1220 реализовал метод получения данных от Pocket посредством Yahoo Query — он действительно работает, однако его надежность при серьезной нагрузке пока непонятна. Так что Pocket у нас пока есть только в наборах кнопок «Мне нравится»:
А проблему с расшариваниями мы еще решим. Ребята из Pocket снова вышли на связь в августе.
2.3 У всех 0, а у Facebook 100500...
Проблемы с отображением могут возникать и более популярных и привычных социальных сервисов. Например, вы можете столкнуться с ошибкой работы кэша Facebook.
Страница была расшарена 0 раз, и это показывают все счетчики, кроме Facebook, который закешировал значение с главной страницы.
Откуда 20? Оказалось, администратор сайта посетил закрытую для гостей страницу с кнопками соцсетей, в Facebook отправился запрос, но соцсеть не получила ответа о доступности страницы и записала себе в кэш число репостов с главной страницы сайта (по редиректу).
Впоследствии этот кэш очень долго не обновляется — и тут помогает только самостоятельный сброс кэша через отладчик Facebook. Аналогичная проблема может встречаться с VK. Чтобы облегчить пользователям процесс отладки, в итоге мы выпустили дебаггер для двух соцсетей разом.
2.4 Борьба с упавшими соцсетями
Поскольку показатели большинства счетчиков никак не зависят от наших действий, а формируются с помощью ответов от соцсетей, мы загружаем все счетчики асинхронно. Кстати, по этой ссылке можно просмотреть форматы запросов для получения шеров большинства популярных соцсетей.
При этом, если мы не получаем ответ от сервера — что бывает при падениях тех же «Вконтакте» и «Моего Мира», то в качестве значения будет отдаваться 0, а в процессе ожидания ответа пользователь будет видеть прелодер счетчика.
2.5 Решение проблемы кривого подсчета и дизайна нативных счетчиков
Как ясно из примера с G+, далеко не всегда стандартные решения социальных сервисов выглядят привлекательно, да и просто понятно для пользователей. Чтобы привести внешний вид счетчиков к единому стандарту, мы занялись оптимизацией отображения сокращений.
Когда материалом деляться очень много людей и цифра на счетчике может зашкалить за over9000, её для красоты лучше сократить.
Вот, как мы это делаем внешне:
А вот так — технически. Для начала мы проверяем, существует ли вообще общий счетчик. Если он существует, то пришедшие от соцсетей ответы записываются в динамически созданный объект
arrSocCounter[id][iconName]
, где arrSocCounter
— объект, а id — URL страницы, которую мы шарим, iconName
— название соцсети (оно же название иконки).С помощью параметра
data-url
получается необходимый набор, а по data-item
мы узнаем, какие соцсети еще остались. Затем цикл проходит по иконкам соцсетей и суммирует нужные значения из ранее полученного объекта arrSocCounter[dataUrl][dataItem]
.И здесь мы подходим к обрезанию больших цифр. Перед тем, как добавить в счетчик полученный результат, его нужно транслировать в понятный системе формат — сериализовать. Затем мы подсчитываем количество элементов в строке, чтобы понять, имеем мы дело с миллионом, тысячей или десятком шеров. Проверять, пришло ли в ответ целое или десятичное число в этом случае нет смысла (статьей не может поделиться 20,5 человек), поэтому можно сразу переходим к подсчету символов в строке.
Если количество находится в диапазоне от 4 до 6 символов включительно, то значение приводится к плавающей точке и округляется до десятичного:
parseFloat(value / 1000).toFixed(1)
. В принципе, на этом можно было бы остановиться, но тогда значение было бы неточным — нас это не устраивает, поэтому мы преобразуем значение в строку и отрезаем два последних символа, к примеру 1001:var val;
val = parseFloat(1001 / 1000).toFixed(1);
console.log(val)
После выполнения этих действий мы получаем число с плавающей точкой 1.0. Затем его следует «перегнать» обратно в строку и отрезать еще два последних символа, добавив к окончательному результату букву “K”:
var valOutput;
valOutput = String(val).slice(val.lenght, -2) + 'k';
console.log(valOutput);
var val,valOutput;
val = parseFloat(1001 / 1000).toFixed(1);
valOutput = String(val).slice(val.lenght, -2) + 'k';
console.log(valOutput);
Заключение и нерешенная задачка
Даже такая не сильно сложная на первый взгляд задача, как создание качественного сервиса социальных кнопок, связана с определенными трудностями. И есть проблема, которую мы не смогли решить красиво.
http =/= https
Интересный и неочевидный момент — часто соцсети и их API воспринимают количество шеров для сайтов с http и https по-разному. То есть, считают, что перед ними два разных сайта — и если раньше владелец ресурса переходил на https, ему нужно было морально готовиться к тому, что на всех его прошлых материалах пропадет количество расшариваний.
Пока мы нашли выход-костыль: добавить data-url=«site.com» и передавать параметр URL без http — если сильно хочется сохранить показатели.
Но, возможно, у сообщества есть идеи по более красивому решению.
***
На этом все, спасибо за внимание, и будем рады ответить на вопросы и обсудить проблему http/https комментариях. А в следующий раз расскажем еще об одной закавыке — работе с кнопками расшаривания для мессенджеров и другими интересными кнопками вроде «в закладки».
* Исследование Nielsen о роли числа лайков и шеров на восприятие статей.
** Статистика по установке наборов «поделиться» с индивидуальными счетчиками для каждой иконки.
Комментарии (5)
G-M-A-X
26.08.2016 09:28>Кроме того, в базе есть отдельные таблицы по каждой соцсети, в которых хранится соответствие хэша URL и поделившимися контентом пользователями.
Как вы получаете ид пользователя? :^)
>Это позволяет, помимо прочего, защититься от накруток шеров одним и тем же пользователем.
Пусть накручивают. Не в этом ли интерес: показать большие числа? :)
>Откуда 20? Оказалось, администратор сайта посетил закрытую для гостей страницу с кнопками соцсетей, в Facebook отправился запрос, но соцсеть не получила ответа о доступности страницы и записала себе в кэш число репостов с главной страницы сайта (по редиректу).
Если это закрытая страница, то может там счетчик не нужно ставить?..
o_Lisovenko
26.08.2016 10:43+1У нас не хранится ID пользователя. Есть урл, уникальные данные пользователя и соц. сеть. Но мы еще работаем над этой системой и стараемся ее улучшать, чтоб ы максимально точно хранить данные и собирать статистику. Но, опять же — по данной системе работают только те соц. сети которые не имею своего API. Это маленький процент, в том числе, как мы видим — это не самые популярные соц. сети.
На счет накруток — ну да, накрутить можно всё и всегда. В целом, мы работаем над защитами, и в одном из будущих постов надеемся раскажем о нашей собственной кнопке лайка — не привязанной к соц сети. Там будут и больше защиты, и умнее условия и логика вывода/хранения информации.
На счет закрытой страницы: на нее специально никто не размещает счетчик. То есть, работает это так:
У вас сайт статей о путешесвиях (блог, вы типичный блогер, возможно даже не знающий толком что такое html). Вы захотели разместить кнопки соц сетей на своем сайте — создаете их и размещаете. На всех страницах. Но не учитываете то, что страница свежего поста может быть на модерации (она закрыта, но она существует, просто FB ее не видит). Ну и отсюда растут проблемы. Можно конечно прописать условие не выводить код кнопок на странице неактивного материала — но это не каждый может и не каждый знает о необходимости.
Dreyk
Если у вас все доступно по https, можно просто включить HSTS