Одной из задач в проекте Вакансии по технологиям InterSystems, было создание кнопок «поделиться» для основных, на наш взгляд, социальных сетей. А конкретно для каждой вакансии необходимо:
- внесение её логотипа;
- название вакансии;
- краткое описание;
- знать из какой соц. сети пришел пользователь.
Как ни странно, это оказалось не такой уж и простой задачей при реализации на AngularJS
- соц. сети сами производят парсинг сайта и собирают информацию с него, игнорируя JavaScript;
- использование open graprh ogp.me динамических метатегов на AngularJS затруднено, т.к. без JavaScript виден только шаблон index.html, а наполнение страницы происходит через RESTful в формате JSON, используя для оформления партиции, формируемые AngularJS в итоговую страницу на клиенте;
- простой шаринг через URL не позволяет передать всю требуемую информацию;
- кроме того, практически все соц. сети режут дополнительные параметры в URL начиная с первого &, т.е. от ссылки soc.csp?id=555&soc=vk останется soc.csp?id=555.
В итоге, все необходимые функции реализованы на отдельной CSP странице. Логика простая и универсальная для большинства веб проектов и описана ниже. Наиболее часто такой подход используется в баннерных системах и при фиксации перехода на внешние ресурсы.
Итак
Даём соц. сети ссылку на промежуточную страницу, на ней размещаем информацию, которую хотим расшарить, соц. сеть выкладывает у себя ссылку на неё, при клике на эту ссылку наша страница перенаправляет пользователя на нужную вакансию. Преимущество такого подхода — скорость. Соц. сеть не парсит сайт целиком в поисках описания и нужных тэгов, а получает только необходимую информацию, к тому же становится возможным фиксировать переходы, даже если соц. сеть возвращает пустой реферер.
Краткая схема работы:
каждой кнопке
соответствует свой URL состоящий из следующих элементов:
- URL соц. сети в которой расшарим ссылку, например www.facebook.com/sharer/sharer.php?u=
- Ссылка на созданный нами файл soc.csp
- Идентификатор вакансии состоит из двух частей — id вакансии в БД и идентификатора соц. сети id={{vacID}}-facebook.com
- Версии проектов dev и product, не считая данных, отличаются только путями к ресурсам (http://localhost::57772/.../soc.scp и cache-vacancies.intersystems.ru/soc.scp) поэтому, что бы не переписывать этот участок кода передаём эту строку в rootURL для формирования абсолютного URL передающегося в соц. сеть
- Конкретная вакансия передаётся в vacID в контроллере AngularJS var vacID = $routeParams.vacID;
Исходные коды
Со стороны клиента:
<div class="span4">
<a style="text-decoration: none;" target="_blank" href="http://www.facebook.com/sharer/sharer.php?u={{rootURL}}soc.csp?id={{vacID}}-facebook.com">
<img src="img/social_icons/Facebook.png">
</a>
<a style="text-decoration: none;" target="_blank" href="http://vkontakte.ru/share.php?url={{rootURL}}soc.csp?id={{vacID}}-vk.com">
<img src="img/social_icons/VK.png">
</a>
<a style="text-decoration: none;" target="_blank" href="http://twitter.com/share?url={{rootURL}}soc.csp?id={{vacID}}-twitter.com&text={{txtVacancyName}}  {{txtsoc}}">
<img src="img/social_icons/Twitter.png">
</a>
<a style="text-decoration: none;" target="_blank" href="https://plus.google.com/share?url={{rootURL}}soc.csp?id={{vacID}}-plus.google.ru">
<img src="img/social_icons/Google.png">
</a>
<a style="text-decoration: none;" target="_blank" href="http://www.odnoklassniki.ru/dk?st.cmd=addShare&st.s=1&st._surl={{rootURL}}soc.csp?id={{vacID}}-odnoklassniki.ru">
<img src="img/social_icons/OK.png">
</a>
<a style="text-decoration: none;" target="_blank" href="http://connect.mail.ru/share?share_url={{rootURL}}soc.csp?id={{vacID}}-mail.ru">
<img src="img/social_icons/Mail.png">
</a>
</div>
<!doctype html>
<html xmlns:fb="http://www.facebook.com/2008/fbml" xmlns:og="http://ogp.me/ns#">
<script language="Cache" runat="Server">
// разбивая REFERER
// получаем id вакансии
set id=$piece($Get(%request.Data("id",1),1),"-")
// узнаём откуда пришли
set ref=$piece($Get(%request.Data("id",1),1),"-",*)
set vacancy =##class(Vacancy.Vacancy).%OpenId(id)
// выводим в консоль
w %request.GetCgiEnv("HTTP_REFERER")
</script>
<head>
<!-- название вакансии (необязательно) -->
<title>#(a.Name)#</title>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<!-- название вакансии -->
<meta property="og:title" content="#(vacancy.Name)#" />
<!-- описание вакансии -->
<meta property="og:description" content="#(vacancy.AddInfo)#" />
<!-- ссылка на изображение вакансии -->
<meta property="og:image" content=#(##class(WEB.JSON).GetDataFromGlobal("URL"))#csp/vacancy/WEB.Image.cls?id=#(id)#&counter=0&ref=#(ref)#" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="супер сайт" />
<meta property="fb:admins" content="" />
</head>
<body>
<script type="text/javascript">
/* т.к. этот блок игнорируется парсером соц. сетей он отрабатывается
только при переходе по ссылке из соц. сети пользователь уходит на целевую страницу с вакансией */
document.location.href="#(##class(WEB.JSON).GetDataFromGlobal("URL"))#csp/vacancy/index.html#/vacancy/#(id)#";
</script>
</body>
</html>
Class Vacancy.Vacancy Extends (%Persistent, %Populate)
{
/// Наименование вакансии
Property Name As %String(MAXLEN = 200);
/// Дополнительное описание
Property AddInfo As %Text(MAXLEN = 5000);
}
Теперь объясню как это работает, а так же кто и какие тэги использует
- В заголовке тега
<HTML>
файла, формирующего требуемую информацию, указываем ссылку на формат ogp - Затем разбиваем реферер на 2 части, для определения из какой соц. сети к нам пришли. Далее загружаем в vacancy данные о запрошенной вакансии, после мы можем обратиться к интересующим нас полям и заполнить соответствующие тэги:
- og:title определяет заголовок ссылки
- og:description описание ссылки
- og:image изображение которое будет использовано, т.к. изображение храниться в БД, мы обращаемся к нему ч/з класс, в общем случае здесь указывается URL изображения
- og:type указываем что передаваемый контент, это веб сайт, а например не видеоролик
- og:site_name передаём название нашего сайта
Проверено на соц. сетях:
Twitter, Одноклассники, Мой мир, Facebook, Google+ и Вконтакте.
При небольшой доработке счётчика посетителей, используя составной параметр, возможно самостоятельно считать пришедших с соц. сетей.
В результате получаем:
А на странице соц. сети:
Обобщая выше сказанное, а так же опыт работы над проектом, привожу следующие наблюдения, подводные камни и способы их обхода:
- facebook не принимает маленькие картинки и символ # в URL ссылки, как следствие указали в скрипте document.location.href= для перехода на нужную страницу
- сбросить кэш facebook можно по ссылке developers.facebook.com/tools/debug
в частности там можно увидеть что размер изображений для этой сети, должен быть не менее чем 200 на 200 пикселей, а так же другие рекомендации по отладке Вашего кода - на странице soc.csp можно увидеть что Вконтакте возвращает id посетителя (http://vk.com/idXXXXX), а facebook возвращает пустоту, как будто пользователь сам набрал ссылку в браузере. А т.к. нам дают указать только 1 параметр в ссылке на ресурс, мы формируем свой составной параметр, который затем преобразуем в набор id и тип сети. Например ?id=27-vk.com.
- в soc.csp мы не стали реализовывать возврат referer в БД — запись посетителя ведётся при обращении к изображению вакансии ч/з класс WEB.Image.cls поэтому в БД хранятся записи вида:
cache-vacancies.intersystems.ru/soc.csp?id=33-facebook.com
cache-vacancies.intersystems.ru/soc.csp?id=33-vk.com - ресурс мой мир mail.ru не позволяет в URL изображений указывать более одного параметра, например если параметра 2, то картинка игнорируется
- некоторые соц. сети и особенно Вконтакте, не любят сервисы доменов привязанных к внешним динамическим IP, выдаваемым Интернет провайдерами (например dyndns или no-ip), а так же белые IP не привязанные к доменам. Соответственно они блокируют переход на них по Вашим ссылкам, поэтому приходится проверять не только факт появления ссылки в соц. сети, но и работу перехода с неё на ресурс
- хотя формат ogp позволяет передать несколько значений одного параметра, например несколько изображений на выбор пользователя, не во всех соц. сетях это работает.
Вместо заключения
Открытую версию проекта «Вакансии» можно найти здесь.. Проект реализован в связке REST+Caché+AngularJS+BootStrap 2, простой пример. Это наш первый, но не последний проект на технологиях InterSystems. Если интересно можем поделиться первыми впечатлениями от стека технологий InterSystems, или поделиться опытом по любому из проектов.
Автор: login4all