Рубрики
CSP Caché

Социальные кнопки в проекте на Caché

Одной из задач в проекте Вакансии по технологиям InterSystems, было создание кнопок “поделиться” для основных, на наш взгляд, социальных сетей. А конкретно для каждой вакансии необходимо:

  • внесение её логотипа;
  • название вакансии;
  • краткое описание;
  • знать из какой соц. сети пришел пользователь.

Как ни странно, это оказалось не такой уж и простой задачей при реализации на AngularJS

  • соц. сети сами производят парсинг сайта и собирают информацию с него, игнорируя JavaScript;
  • использование open graprh динамических метатегов на AngularJS затруднено, т.к. без JavaScript виден только шаблон index.html, а наполнение страницы происходит через RESTful в формате JSON, используя для оформления партиции, формируемые AngularJS в итоговую страницу на клиенте;
    т.е. вместо желаемой информации:
    они видят только главный шаблон index.html:
  • простой шаринг через URL не позволяет передать всю требуемую информацию;
  • кроме того, практически все соц. сети режут дополнительные параметры в URL начиная с первого &, т.е. от ссылки soc.csp?id=555&soc=vk останется soc.csp?id=555.

В итоге, все необходимые функции реализованы на отдельной CSP странице (CSP-Caché Server Pages). Логика универсальная для большинства веб-проектов и описана ниже. Наиболее часто такой подход используется в баннерных системах и при фиксации перехода на внешние ресурсы.

Итак

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

Краткая схема работы:


каждой кнопке с логотипом соц. сети: soc-buttons соответствует свой URL состоящий из следующих элементов:

  1. URL соц. сети в которой расшарим ссылку, например http://www.facebook.com/sharer/sharer.php?u=
  2. Ссылка на созданный нами файл soc.csp
  3. Идентификатор вакансии состоит из двух частей – id вакансии в БД и идентификатора соц. сети id={{vacID}}-facebook.com
  4. Версии проектов dev и product, не считая данных, отличаются только путями к ресурсам (http://localhost:57772/…/soc.scp и http://cache-vacancies.intersystems.ru/soc.scp) поэтому, чтобы не переписывать этот участок кода передаём эту строку в rootURL для формирования абсолютного URL передающегося в соц. сеть, в общем случае достаточно указать абсолютный URL на страницу которую хотим расшарить;
  5. Конкретная вакансия передаётся в vacID в контроллере AngularJS var vacID = $routeParams.vacID;

Исходные коды

Ссылка на репозиторий с полной работоспособной версией всего проекта (включая админку, структуру базы и обработчики) указана в конце поста. Структура веб-части идентична рекомендованной для AngularJS. Поэтому привожу отрывки кодов в рамках темы поста, достаточной для самостоятельной реализации и для удобства ориентирования в репозитории.

Со стороны клиента:

отрывок с использованием AngularJS в vacancy.html:

<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}}&nbsp {{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>

формирование rootURL и VacID в controllers.js

function vacancyCtrl($scope, $http,  $cookies, $window, configProvider, configProviderNA){
    $window.document.title="Вакансии по технологиям InterSystems";
    // получим из менеджера конфигурации корневой адрес
    if ($scope.rootURL == undefined && $cookies.login != undefined){
        configProvider.getURL(function(data){
            $scope.rootURL = data.URL;
        })
    }

    // если корневой адрес не заполнен - попытаемся получить из неавторизованного доступа
    if ($scope.rootURL == undefined && $cookies.login == undefined){
        configProviderNA.getURL(function(data){

            $scope.rootURL = data.URL;
        })
    }
/*остальная часть кода в репозитории*/
}
function vacancyShowCtrl($scope,$http, $routeParams, $window, $cookies, configProvider, configProviderNA){
    //текущая вакансия передаётся по ссылке;
    var vacID = $routeParams.vacID;
/*остальная часть кода в репозитории*/
}

страница – посредник soc.csp целиком

<!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>

Часть текста класса Vacancy.Vacancy.cls

Class Vacancy.Vacancy Extends (%Persistent, %Populate)
{
/// Наименование вакансии 
Property Name As %String(MAXLEN = 200);

/// Дополнительное описание
Property AddInfo As %Text(MAXLEN = 5000);
}

Теперь объясню как это работает, а так же кто и какие тэги использует

  1. В заголовке тега <HTML> файла, формирующего требуемую информацию, указываем ссылку на формат ogp
  2. Затем разбиваем реферер на 2 части, для определения из какой соц. сети к нам пришли. Далее загружаем в vacancy данные о запрошенной вакансии, после мы можем обратиться к интересующим нас полям и заполнить соответствующие тэги:
  • og:title определяет заголовок ссылки
  • og:description описание ссылки
  • og:image изображение которое будет использовано, т.к. изображение хранится в БД, мы обращаемся к нему через класс, в общем случае здесь указывается URL изображения
  • og:type указываем что передаваемый контент, это веб сайт, а, например, не видеоролик
  • og:site_name передаём название нашего сайта

Проверено на соц. сетях:
Twitter, Одноклассники, Мой мир, Facebook, Google+ и Вконтакте.

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


А на странице соц. сети:

Обобщая выше сказанное, а так же опыт работы над проектом, привожу следующие наблюдения, подводные камни и способы их обхода:

  • facebook не принимает маленькие картинки и символ # в URL ссылки, как следствие указали в скрипте document.location.href= для перехода на нужную страницу
  • сбросить кэш facebook можно по ссылке https://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 поэтому в БД хранятся записи вида:
    http://cache-vacancies.intersystems.ru/soc.csp?id=33-facebook.com http://cache-vacancies.intersystems.ru/soc.csp?id=33-vk.com
  • ресурс мой мир mail.ru не позволяет в URL изображений указывать более одного параметра, например если параметра 2, то картинка игнорируется
  • некоторые соц. сети и особенно Вконтакте, не любят сервисы доменов привязанных к внешним динамическим IP, выдаваемым Интернет провайдерами (например dyndns или no-ip), а так же белые IP не привязанные к доменам. Соответственно они блокируют переход на них по Вашим ссылкам, поэтому приходится проверять не только факт появления ссылки в соц. сети, но и работу перехода с неё на ресурс
  • хотя формат ogp позволяет передать несколько значений одного параметра, например несколько изображений на выбор пользователя, не во всех соц. сетях это работает.

Коротко о проекте

Проект “Вакансии по технологиям InterSystems” предназначен для размещения информации о новых вакансиях партнёров компании. Проект и примеры ниже реализованы в связке REST+Caché+AngularJS+BootStrap 2.

Вместо заключения

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *