В погоне за удобством посетителей или умные ссылки
Здравствуйте.
У многих на сайтах есть блок с похожими статьями, как правило их выбирают из тех же категорий или используют теги. Но не все ссылки (статьи) в этих блоках одинаково полезны для посетителей, и если проверить, то на одни кликают часто, на другие крайне редко.
Почему бы не сделать так, что бы оставались только те ссылки которые максимально релевантны статье, причем пользователи, не замечая того, сами решаю какие ссылки им полезны. Так мы убиваем двух зайцев, пользователю удобно, а у сайта улучшаются показатели глубины просмотра и времени на сайте — вовлеченности пользователей.
Ниже привожу свои потуги на реализацию данного решения. Сразу хочу отметить, что я далеко не программист, поэтому думаю, что многое можно сделать намного лучше и правильнее и в моем решении могут присутствовать косяки.
Если вас так же как и меня интересует данная идея, предлагаю совместно улучшать, а если кто либо способен создать нормальный пакет, это было бы превосходно.
Начну
Потребуется создать:
1. чанк — [[$smartchank?]];
2. сниппет [[!ajaxsmart?]] — обработчик;
3. [[smartsnipetoutput? &smartblname=`smartblock`]] сниппет вывода, где &smartblname=`smartblock` имя tv в которую записываем;
4. одно (или несколько, зависит от числа блоков с ссылками) доп. поле — smartblock (доступно для шаблона со статьями)
Все что приведу ниже, это просто скопировал с своего сайта, в вашем случае возможно что-то придется допиливать.
Структура сайта: категория — подкатегория — статьи
1. Вывод материалов на странице статьи
шаблон tpllinkpost
data-action=«smartblock,[[+id]],3» где smartblock имя tv — придуманное название для блока со ссылками (если блоков на странице несколько для каждого свое tv), 3 -число ссылок в блоке (на ваше усмотрение)
[[+id]] — id документа по ссылке
[[smartsnipetoutput? &smartblname=`smartblock`]] — сиппет который из общий счетчик кликов, id1 статьи, счет кликов по id1, id2 статьи, счет кликов по id2, id3 статьи, счет кликов по id3 делает id1,id2,id3,
[[smartsnipetoutput? &smartblname=`smartblock`]] где &smartblname=`smartblock` имя tv из которой читаем.
[[$smartchank?]]
Логика
1. Пользователь кликает по ссылке с похожими статьями
2. id материала и придуманное название блока со ссылками (нужно для размещения нескольких блоков на странице) передаем в сниппет ajaxsmart, через ajax (спасибо Василию за статью)
3. проверяем, если доп. поле пустое, записываем в него случайные статьи (в моем случае 3 шт)
формат доп. поля
общий счетчик кликов, id1 статьи, счет кликов по id1, id2 статьи, счет кликов по id2, id3 статьи, счет кликов по id3,…
4. если поле уже не пустое, находим id (статьи) переданной по ссылке и прибавляем для нее счетчик (+1)
5. Если было более 9 кликов (общий счетчик) (так мало установил для теста)
Косяки которые нашел, но не устранил
1. в наше id, после случайной выборки может попасть id которое уже есть в списке
2. в наше id, после случайной выборки может попасть id самой статьи
Отказ от ответственности
Звучит мощно :)
Так как по моему коду сразу видно уровень моих знаний, прошу строго не судить, при реализации могут быть проблемы которые я не смогу решить.
Надеюсь будут грамотные специалисты которых заинтересует такая задача и будет реализован готовый пакет, так же с радостью принимаются любые доработки и улучшения.
Надеюсь пригодится не только мне и спасибо сообществу за помощь и куски кода которые подсказывали.
У многих на сайтах есть блок с похожими статьями, как правило их выбирают из тех же категорий или используют теги. Но не все ссылки (статьи) в этих блоках одинаково полезны для посетителей, и если проверить, то на одни кликают часто, на другие крайне редко.
Почему бы не сделать так, что бы оставались только те ссылки которые максимально релевантны статье, причем пользователи, не замечая того, сами решаю какие ссылки им полезны. Так мы убиваем двух зайцев, пользователю удобно, а у сайта улучшаются показатели глубины просмотра и времени на сайте — вовлеченности пользователей.
Ниже привожу свои потуги на реализацию данного решения. Сразу хочу отметить, что я далеко не программист, поэтому думаю, что многое можно сделать намного лучше и правильнее и в моем решении могут присутствовать косяки.
Если вас так же как и меня интересует данная идея, предлагаю совместно улучшать, а если кто либо способен создать нормальный пакет, это было бы превосходно.
Начну
Потребуется создать:
1. чанк — [[$smartchank?]];
2. сниппет [[!ajaxsmart?]] — обработчик;
3. [[smartsnipetoutput? &smartblname=`smartblock`]] сниппет вывода, где &smartblname=`smartblock` имя tv в которую записываем;
4. одно (или несколько, зависит от числа блоков с ссылками) доп. поле — smartblock (доступно для шаблона со статьями)
Все что приведу ниже, это просто скопировал с своего сайта, в вашем случае возможно что-то придется допиливать.
Структура сайта: категория — подкатегория — статьи
1. Вывод материалов на странице статьи
<div class="post">
<ol>
[[pdoResources?
&cache=`1` &cacheTime=`864000`
&select=`pagetitle,longtitle,uri,id`
&parents=`[[pdoField? &id=`[[*id]]` &top=`2` &field=`id`]]`
&depth=`1`
&limit=`3`
&tpl=`tpllinkpost`
&hideContainers=`1`
&resources=`[[smartsnipetoutput? &smartblname=`smartblock`]]-[[*id]]`
]]
</ol>
</div>где [[pdoField? &id=`[[*id]]` &top=`2` &field=`id`]] — получаем id категориишаблон tpllinkpost
<a data-action="smartblock,[[+id]],3" class="ajax_link" title="[[+pagetitle]]" href="[[++site_url]][[+uri]]">[[+longtitle]]</a>основное здесь это data-action=«smartblock,[[+id]],3» где smartblock имя tv — придуманное название для блока со ссылками (если блоков на странице несколько для каждого свое tv), 3 -число ссылок в блоке (на ваше усмотрение)
[[+id]] — id документа по ссылке
[[smartsnipetoutput? &smartblname=`smartblock`]] — сиппет который из общий счетчик кликов, id1 статьи, счет кликов по id1, id2 статьи, счет кликов по id2, id3 статьи, счет кликов по id3 делает id1,id2,id3,
[[smartsnipetoutput? &smartblname=`smartblock`]] где &smartblname=`smartblock` имя tv из которой читаем.
<?php
$smartblock= $modx->resource->getTVValue("$smartblname");
$strcount = strlen($smartblock);
if($strcount>1)
{ $smartmas = explode(",", $smartblock);
$smartmascount=count($smartmas);
$i=1;
while ($i<($smartmascount-1))
{ echo $smartmas[$i].",";
$i=$i+2;
}
}2. в шаблоне вызываем чанк и сниппет[[$smartchank?]]
<script type="text/javascript">
$(document).ready(function() {
// Вешаем обработчик события "клик" на все ссылки с классом ajax_link
$('a.ajax_link').click(function() {
// Берем действие из атрибута data-action ссылки
var action = $(this).data('action');
// Ajax запрос к текущей страницы (а на ней наш сниппет) методом post
$.post(document.location.href, {action: action}, function(data) {
$('#result').html(data);
})
})
})
</script>[[!ajaxsmart?]]<?php
// Откликаться будет ТОЛЬКО на ajax запросы
if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;}
// Сниппет будет обрабатывать не один вид запросов, поэтому работать будем по запрашиваемому действию
// Если в массиве POST нет действия - выход
if (empty($_POST['action'])) {return;}
$res2 = $_POST['action'];
$input = explode(",", $res2);
$nblock = $input[0]; //получаем имя tv
$idlink = $input[1]; // получаем id (документа) ссылки по которой кликнули
$lenblok = $input[2]; // получаем число ссылок в блоке (должно быть одинаковое со значением &limit=`3` в pdoResources)
$smartblock= $modx->resource->getTVValue($nblock);
$strcount = strlen($smartblock);
if($strcount<=1) {
$resource = $modx->resource;//получили объект ресурс
$idpar = $modx->resource->get('parent');//получили его родителя
$res = $modx->getObject('modResource',$idpar);//получили объект родитель
$parentId= $modx->getParentIds($idpar, 1);
$childIds = $modx->getChildIds($parentId[0], 1);
$result = array();
$q = $modx->newQuery('modResource', array('parent:IN' => $childIds));
$q->select('id');
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row['id'];
}
}
$idallmas = $result;
$len = count($idallmas)-1;
function RSUI($n, $min, $max) {
$numbers = array();
while (count($numbers) < $n) {
$number = mt_rand($min, $max);
if (!in_array($number, $numbers)) {
$numbers[] = $number;
}
}
return $numbers;
}
$rndmas=RSUI($lenblok, 0, $len); //&lenblok=`3` параметр сниппета
$x=1;
$idmasout[0]=1;
for ($i=0; $i<$lenblok; $i++) {
$idmasout[$x]=$idallmas[$rndmas[$i]];
$x=$x+1;
$idmasout[$x]=0;
$x=$x+1;
}
$strtv = implode(",", $idmasout);
$resource->setTVValue($nblock, $strtv);
$resource->save();
$resource->clearCache();
}
else {
$resource = $modx->resource;//получили объект ресурс
$id = $modx->resource->get('id');//id текущего ресурса
$massmart = explode(",", $smartblock);
$len = count($massmart);
$min=$massmart[1]; $minid=1;
$massmart[0]=$massmart[0]+1;
for ($i=1; $i<$len; $i++) {
if(($i % 2) == 0){
if ($min>$massmart[$i]) {$min=$massmart[$i]; $minid=$i;}
}
else {
if ($massmart[$i]==$idlink) {$massmart[$i+1]=($massmart[$i+1])+1;}
}
}
if ($massmart[0]>9) {
$resource = $modx->resource;//получили объект ресурс
$idpar = $modx->resource->get('parent');//получили его родителя
$res = $modx->getObject('modResource',$idpar);//получили объект родитель
$idparentglav =$res->get('parent');//получили родителя-родителя
$parentId= $modx->getParentIds($idpar, 1);
$childIds = $modx->getChildIds($parentId[0], 1);
$idallmas = array();
$q = $modx->newQuery('modResource', array('parent:IN' => $childIds));
$q->select('id');
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$idallmas[] = $row['id'];
}
}
$len1 = count($idallmas)-1;
$number = mt_rand(0, $len1);
$massmart[$minid-1]=$idallmas[$number];
for ($i=2; $i<$len; $i=$i+2) {$massmart[$i]=0;}
$massmart[0]=1;
}
$strtv = implode(",", $massmart);
echo $strtv;
$resource->setTVValue($nblock,$strtv); //записать в tv
$resource->save();
$resource->clearCache();
$uri= $modx->resource->get('uri');
$uri="http://".$_SERVER['SERVER_NAME']."/".$uri;
file_get_contents($uri);
}
// Если у нас есть, что отдать на запрос - отдаем и прерываем работу парсера MODX
if (!empty($res2)) {
die();
}Логика
1. Пользователь кликает по ссылке с похожими статьями
2. id материала и придуманное название блока со ссылками (нужно для размещения нескольких блоков на странице) передаем в сниппет ajaxsmart, через ajax (спасибо Василию за статью)
3. проверяем, если доп. поле пустое, записываем в него случайные статьи (в моем случае 3 шт)
формат доп. поля
общий счетчик кликов, id1 статьи, счет кликов по id1, id2 статьи, счет кликов по id2, id3 статьи, счет кликов по id3,…
4. если поле уже не пустое, находим id (статьи) переданной по ссылке и прибавляем для нее счетчик (+1)
5. Если было более 9 кликов (общий счетчик) (так мало установил для теста)
if ($massmart[0]>9), то находим id документа с минимальным числом кликов (счетчиком кликов по ссылке) и заменяем ее на другой id полученный из категории (а не из подкатегории) (обратите внимание — это в моем случае, в ваше случае может быть иначе, зависит от структуры сайта)Косяки которые нашел, но не устранил
1. в наше id, после случайной выборки может попасть id которое уже есть в списке
2. в наше id, после случайной выборки может попасть id самой статьи
Отказ от ответственности
Звучит мощно :)
Так как по моему коду сразу видно уровень моих знаний, прошу строго не судить, при реализации могут быть проблемы которые я не смогу решить.
Надеюсь будут грамотные специалисты которых заинтересует такая задача и будет реализован готовый пакет, так же с радостью принимаются любые доработки и улучшения.
Надеюсь пригодится не только мне и спасибо сообществу за помощь и куски кода которые подсказывали.
Комментарии: 15
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Может быть можно как то страницу, после всех манипуляций, запихнуть обратно в кеш, но как я не додумался.
Конечно с поиском по modx.pro все отлично, но и блок бы, на мой взгляд, не помешал.
Но посмотрел и задумался, даже в категории вопросы, из-за их разнообразия, нужно на основе чего-то делать первичную выборку (иначе кликать толком не будут — первичные материалы будут полностью нерелевантны).
В общем, жаль.
На modx.pro при написании вопроса есть графа «Вопрос связан с работой дополнения:», может быть можно играть и от этого, но опять же, его заполняют сами пользователи и не всегда.
Это было бы зверски удобно. Помню на некоторых форумах, бот сразу отвечает ссылками с заголовками тем форума.
На самом деле подобное расширение достойно быть платным — яб купил.
потестил, страница отправляется в кеш
При изменение статьи, мог где-то накосячить, старался проверить, но кто его знает.
Перед внедрением, тестируйте и еще раз тестируйте, чем и сам продолжаю заниматься.
Удачи.