Over 9000: неочевидні складності роботи з лічильниками соціальних кнопок (+ задачка)



Одна з найбільш затребуваних функцій соціальних кнопок «поділитися» — це лічильник вчинених дій. Мала кількість лайків і шерів може говорити про «неякісності» матеріалу; великі числа, навпаки, служать свого роду соціальним доказом і змушують інших ділитися контентом.

У ситуації з великими числами стають актуальні окремі лічильники для кожної іконки кнопки соцмережі. Однак, навіть простий висновок такого лічильника не завжди просто організувати — з технічної та візуальної точок зору. Простіше кажучи:

  • лічильник може відвалитися в самий невідповідний момент;
  • деякі соціальні сервіси не надають даних про репостах в принципі;
  • а інші не завжди в змозі забезпечити коректну передачу цієї інформації.

Як розробники власний сервісу готових соціальних кнопок 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 користувача. Це дозволяє, крім іншого, захиститися від накруток шерів одним і тим же користувачем.

code
---
// Намагаємося створити запис про кулі
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 про ролі кількості лайків і шерів на сприйняття статей.

** Статистика по установці наборів «поділитися» з індивідуальними лічильниками для кожної іконки.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.