Вендор: СУБД Caché, OLAP DeepSee, шина Ensemble
137,36
рейтинг
2 января 2014 в 17:10

Разработка → Социальные кнопки в проекте на Caché tutorial

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

Как ни странно, это оказалось не такой уж и простой задачей при реализации на AngularJS
  • соц. сети сами производят парсинг сайта и собирают информацию с него, игнорируя JavaScript;
  • использование open graprh ogp.me динамических метатегов на 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). Логика универсальная для большинства веб проектов и описана ниже. Наиболее часто такой подход используется в баннерных системах и при фиксации перехода на внешние ресурсы.

Итак


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

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



каждой кнопке с логотипом соц. сети:
image
соответствует свой URL состоящий из следующих элементов:
  1. URL соц. сети в которой расшарим ссылку, например www.facebook.com/sharer/sharer.php?u=
  2. Ссылка на созданный нами файл soc.csp
  3. Идентификатор вакансии состоит из двух частей — id вакансии в БД и идентификатора соц. сети id={{vacID}}-facebook.com
  4. Версии проектов dev и product, не считая данных, отличаются только путями к ресурсам (http://localhost::57772/.../soc.scp и 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}}  {{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. В заголовке тега файла, формирующего требуемую информацию, указываем ссылку на формат ogp
    Затем разбиваем реферер на 2 части, для определения из какой соц. сети к нам пришли. Далее загружаем в vacancy данные о запрошенной вакансии, после мы можем обратиться к интересующим нас полям и заполнить соответствующие тэги:

  2. Если интересно можем поделиться первыми впечатлениями от стека технологий InterSystems, или поделиться опытом по любому из проектов.
Автор: @login4all
InterSystems
рейтинг 137,36
Вендор: СУБД Caché, OLAP DeepSee, шина Ensemble

Комментарии (7)

  • 0
    А почему нельзя было взять готовый велосипед?
    • +1
      Конечно же пробовали разные варианты, например Pluso. Неудобство в том что он сам считает посетителей и не передаёт их нам, к тому же из за того что эти плагины используют свои перенаправляющие сервера — работает шаринг медленнее, потому что мы выдаём соц. сети только требуемую информацию (около килобайта) и только 1 картинку. Так же это позволяет нам видеть эффективность размещения информации в различных соц. сетях. К тому же не нашли ничего позволяющего обойти игнор javascript парсерами и отвечающее всем стоящим требованиям.
    • +2
      Согласен, есть хорошие варианты — api.yandex.ru/share/ например.

      Свой велосипед это конечно хорошо, быстрее, оптимальней, веселее.

      Но охота ли возится с поддержкой работоспособности всего списка соц. сетей?
      • 0
        Yandex в первую очередь попробовали, изначально не думали что придётся возиться (думали у всех всё одинаково и по описанию легко). В ходе работы появились последние обобщения описанные в конце поста. А результат того стоил.
        • 0
          Я имею ввиду, то что завтра например twitter что-нибудь поменяет в api — придется переделывать, а можно поручить это ребятам из Яндекса :)
          • 0
            Кстати с twitter так и было, надеюсь в любом случае будет какой то конечный список объектов — ссылка, описание, изображение. Храним их целиком в базе. Оптимизм внушает то что формат ogp поддерживает facebook, а сам формат основан на стандарте описания метаданных
  • 0
    поручить это ребятам
    готовый велосипед
    Главное что все сторонние api шаринга, которые мы рассматривали, не передают разработчику информации с которой можно было бы работать.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка