И опять теги: теперь индексируемые

Здравствуйте.
Многие пользуются тегами, но вывод, в большинстве случаев, осуществляется на одной и той же странице с помощью перехвата (GET). Поэтому данные страницы нормально не ранжируются поисковиками. Предлагаю сделать иначе.
ВНИМАНИЕ! Если у вас тысячи и даже сотни тегов, данное решение может только осложнить жизнь, так как оно не автоматизировано.

1. Создаем доп. поле tags (авто-метка, доступное для необходимых шаблонов: статьи, категории)
2. Создаем отдельный раздел с тегами: Теги (в моем случае его id=36) в нем каждый ресурс будет отдельным тегом (Тег1, Тег2,...). Каждому такому ресурсу прописываем в доп. поле по одному тегу соответственно тег1 или тег 2 или…
В содержимое ресурса пропишем чанк [[$tagsview?]]
Код чанка, который будет выводить ресурсы по тегам
<div id="pdopage">
	[[!+page.nav]] 
		<div class="rows">
			  [[!pdoPage? 			      
			          &tpl=`tplteg`
			          &scheme=`full`
				  &ajaxMode=`button`
				  &cache=`1` 
				  &cacheTime=`86400` 
                                  &parents=`0`
                                  &resources=`-[[*id]]`
				  &prepareTVs=`1` 
				  &element=`pdoResources` 
				  &includeTVs=`tags` 
				  &limit=`10` 
				  &hideContainers=`1` 
				  &ajaxTplMore=`@INLINE <button class="btn btn-success btn-more">Показать еще</button>`				  
				  &where=`{"tags:LIKE":"%[[*tags]]%"}`
			   ]] 
		</div>
	[[!+page.nav]]
</div>
код tplteg
<a target="_blank" title="[[+longtitle]]" href="[[++site_url]][[+uri]]">[[+pagetitle]]</a>
3. В месте, где нужно вывести все теги сайта (оно же облако)
[[pdoMenu?
			        &cache=`1`
                                &scheme=`full`
                                &fastMode=`1`
                                &parents=`36`
                                &showHidden=`1`
                                &level=`1`
                                &includeTVs=`tags`
                                &firstClass=``
                                &hereClass=`current-tab`
                                &outerClass=``
                                &tpl=`@INLINE <li[[+classes]]><a title="Статьи «[[+menutitle]]»" href="[[+link]]" [[+attributes]]>[[+tags]]</a>[[+wrapper]]</li>`
                            ]]
где &parents=`36` — это id раздела с тегами
4. Для вывода тегов ресурса используем
[[!pdoResources? 
			                                      
			                &depth=`10` 
                                	&tpl=`@INLINE <a target="_blank" title="[[+longtitle]]" href="[[++site_url]][[+uri]]">[[+tv.tags]]</a>`
                                	&scheme=`full`
                                	&cache=`1` 
                                	&cacheTime=`86400` 
                                        &parents=`36`
                                	&includeTVs=`tags` 
                                	&limit=`6` 
                                	&hideContainers=`1`
                                	&where=`[[tegLike?]]`
                                	&sortby=`{"tags":"ASC"}`                                			      
]]
где [[tegLike?]] — сниппет выборки, его код
$tagstv= $modx->resource->getTVValue(tags);
$tagsmas = explode(",", $tagstv);
$len = count($tagsmas);
for ($i=1; $i<$len; $i++) {
  $tags= $tags."OR tags LIKE '".$tagsmas[$i]."'"; 
} 
if ($len>0) {$tags="tags LIKE '".$tagsmas[0]."'".$tags;}
$tags="(".$tags.")";
return $tags;
5. (чуть не забыл этот пункт, добавляю). Для добавления тегов, при публикации статей с фронта.
Все знают, замечательное дополнение tickets и его возможность добавлять статьи с фронта. Добавляем в его форму — теги.
а. вызов на странице TicketForm и сниппетов авторизации
[[!TicketForm? 
&requiredFields=`longtitle,introtext` 
&allowedFields=`longtitle,fullname,introtext,avtor,tags` 
&redirectUnpublished=`0` 
&parents=`[[!get?]]` 
&tplFormCreate=`tpl.Tickets.form.create1`
&tplFormUpdate=`tpl.Tickets.form.update1 `
 ]]
[[!HybridAuth? &groups=`users`]]     
[[!Login? &contexts=`web,mgr`]]
код tpl.Tickets.form.create1

<script>
    window.onload = function() 
    {
        $("#parentcat [value='[[!get?]]']").attr("selected", "selected");
        if ([[!get?]]!='') {
          document.getElementById('form1').style.display="block";
          document.getElementById('tags').value='';
        } 
    }

  
    function fcreateteg(value) {
        
         len=document.getElementById('tags').value.length;
         if(len<70){
             allteg=document.getElementById('tags').value+=value+',';
         }
   
    document.getElementById(value).style.display = "none";
        
        
    }

    function delznak() {  
        var allteg = document.getElementById('tags').value;   
        var allteg=allteg.slice(0, -1);       
        document.getElementById('tags').value=allteg; 
    }
    
    function fclear() {
        mem=document.getElementById('tags').value;
        document.getElementById('tags').value='';             
        var arr = mem.split(',');
        lenar=arr.length;
        i=0;
        while (i < lenar) {
          document.getElementById(arr[i]).style.display = '';            
          i++;
        }        
    }
</script>

<div class="well create">
    <form name="ticketFormcat" action="" id="ticketFormcat" method="get" >
        <div class="form-group">
	    	<label  for="ticket-sections">Раздел <span style="color: #F00;font-size: 12px;}">(выберите в первую очередь)</span></label>
                <select name="parentcat" class="form-control" id="parentcat" onchange="if (this.selectedIndex) this.form.submit ()">
                       <option  value="" ></option>
                        [[pdoMenu?
                        &parents=`0`
                        &level=`1`
                        &firstClass=``
                        &lastClass=``
                        &hereClass=``
                        &outerClass=``
                        &tplOuter=`@INLINE [[+wrapper]]`
                        &tpl=`@INLINE <option value="[[+id]]">[[+menutitle]]</option>`
                    ]]
            </select>
        </div>
    </form>
</div> 


<div id="form1" style="display:none;" class="well create">    
<form  method="post" action="" id="ticketForm">
	<div id="ticket-preview-placeholder"></div>

	<input type="hidden" name="tid" value="0" />
            
	<div class="form-group">
		<label  for="ticket-sections">[[%tickets_section]]</label>
		<select name="parent" class="form-control" id="ticket-sections">[[+sections]]</select>
		<span class="error"></span>
	</div>
	
	<div class="form-group">
		<label for="ticket-pagetitle">[[%ticket_pagetitle]]<span class="remark1"> (до 100 символов)</span></label>
		<input type="text" class="form-control" placeholder="[[%ticket_pagetitle]]" name="pagetitle" value="" maxlength="150" id="ticket-pagetitle"/>
		<span class="error"></span>
	</div>
	<div class="form-group">
		<label for="ticket-longtitle">Расширенный заголовок<span class="remark1"> (до 150 символов)</span></label>
		<input type="text" class="form-control" placeholder="Расширенный заголовок" name="longtitle" value="" maxlength="150" id="ticket-longtitle"/>
		<span class="error"></span>
	</div>
	<div class="form-group">
		<label for="ticket-avtor">Автор статьи</label>
		<input type="text" class="form-control" placeholder="Автор статьи" name="avtor" value="" maxlength="50" id="ticket-avtor"/>
		<span class="error"></span>
	</div>
	<div class="form-group">
		<label for="ticket-introtext">Аннотация <span class="remark1"> (до 200 символов, краткое содержимое статьи)</span></label>
			<textarea class="form-control" placeholder="кратко о чем статья" name="introtext" id="ticket-introtext" maxlength="200" rows="4"></textarea>
		<span class="error"></span>
	</div>
	<div id="tagi" class="form-group">
    	<label for="ticket-sections">Теги к статье </label>
        <select  multiple size="10" name="tagi" class="form-control" id="ticket-sections" onchange="fcreateteg(value);">
                   
                   [[pdoResources?
                                    &parents=`36`
                                    &depth=`0`
                                    &includeTVs=`tags`
                                    &tpl=`@INLINE <option id="[[+tv.tags]]">[[+tv.tags]]</option>` 
                                ]]  
                    
         </select>
         
		<span class="error"></span>
        <label for="ticket-sections">Выбранные теги</label> <a style="color: rgb(85, 170, 218);cursor: pointer; float: right;" class="tegiform" onclick="fclear();">очистить</a>
        <input  readonly type="text" class="form-control" placeholder="Выбранные теги" name="tags" value="" maxlength="350" id="tags"/>
	</div>
	
	
	<div class="form-group">
		<textarea class="form-control" placeholder="[[%ticket_content]]" name="content" id="ticket-editor" rows="10"></textarea>
		<span class="error"></span>
	</div>
	
	 </div>`]]	
	
	
		[[+files]]
	</div>

	<div class="form-actions row">
		<div class="col-md-6">
			<input type="button" class="btn btn-default preview" value="[[%ticket_preview]]" title="Ctrl + Enter" />
		</div>
		<div class="col-md-6 move-right">
			<input type="submit" class="btn btn-danger draft" name="draft" value="[[%ticket_draft]]" title="Ctrl + Shift + Enter" onclick="delznak();" />
			<input type="button" class="btn btn-primary publish" name="publish" value="[[%ticket_publish]]" title="" onclick="delznak();" />
		</div>
	</div>
</form>

</div>
Внимание привожу код tpl.Tickets.form.update1 (он только для примера, выдернул с сайта без переделки и проверки)
<style>
.mce-container, .mce-container-body {overflow:hidden;}
.mce-splitbtn .mce-open {display:none;}
.mce-btn .mce-txt {font-size:18px!important;font-weight:bold;opacity:.9;}
</style>

<script> 

    function fcreateteg(value) {
        
         len=document.getElementById('tags').value.length;
         if(len<70){
             allteg=document.getElementById('tags').value+=value+',';
         }
   
    document.getElementById(value).style.display = "none";
        
    }


    function delznak() {  
        var allteg = document.getElementById('tags').value;   
        var allteg=allteg.slice(0, -1);       
        document.getElementById('tags').value=allteg; 
    }
    

    function fclear() {
        mem=document.getElementById('tags').value;
        document.getElementById('tags').value='';
          
       
        var arr = mem.split(',');
        lenar=arr.length;
        i=0;
        while (i < lenar) {
          document.getElementById(arr[i]).style.display = ''; 
           
          i++;
        }
        
    }
</script>

<form class="well update" method="post" action="" id="ticketForm">
    <div id="ticket-preview-placeholder"></div>

    <input type="hidden" name="tid" value="[[+id]]"/>

    <div class="form-group">
        <label for="ticket-sections">[[%tickets_section]]</label>
        <select name="parent" class="form-control" id="ticket-sections">[[+sections]]</select>
        <span class="error"></span>
    </div>
    <div class="form-group">
		<label for="ticket-avtor">Автор</label>
		<input type="text" class="form-control" placeholder="[[%ticket_avtor]]" name="avtor" value="[[+avtor]]" maxlength="50" id="ticket-avtor"/>
		<span class="error"></span>
	</div>

    <div class="form-group">
        <label for="ticket-pagetitle">[[%ticket_pagetitle]]</label>
        <input type="text" class="form-control" placeholder="[[%ticket_pagetitle]]" name="pagetitle"
               value="[[+pagetitle]]" maxlength="50" id="ticket-pagetitle"/>
        <span class="error"></span>
    </div>
    
	<div class="form-group">
		<label for="ticket-longtitle">Название статьи</label>
		<input type="text" class="form-control" placeholder="[[%ticket_longtitle]]" name="longtitle" value="[[+longtitle]]" maxlength="150" id="ticket-longtitle"/>
		<span class="error"></span>
	</div>
	
	<div class="form-group">
		<label for="ticket-description">Description к статье</label>
			<textarea class="form-control" placeholder="[[%ticket_description]]" name="description"  id="ticket-description" maxlength="200" rows="3">[[+description]]</textarea>
		<span class="error"></span>
	</div>
		<div class="form-group">
		<label for="ticket-introtext">Аннотация к статье</label>
			<textarea class="form-control" placeholder="[[%ticket_introtext]]" name="introtext" id="ticket-introtext" maxlength="200" rows="3">[[+introtext]]</textarea>
		<span class="error"></span>
	</div>
	<div id="tagi" class="form-group">
                	<label for="ticket-sections">Теги к статье </label>
                    <select  style="max-width: 708px;" multiple size="5" name="tagi" class="form-control" id="ticket-sections" onchange="fcreateteg(value);">
                               [[pdoResources?
                                    &parents=`81`
                                    &depth=`0`
                                    &includeTVs=`tags`
                                    &tpl=`@INLINE <option id="[[+tv.tags]]">[[+tv.tags]]</option>` 
                                ]]
                     </select>
                      
            		<span class="error"></span>
                    <label style="margin-top: 10px;" for="ticket-sections">Выбранные теги</label> <a style="color: rgb(85, 170, 218);cursor: pointer; float: right;" class="tegiform" onclick="fclear();">очистить</a>
                    <input  readonly type="text" class="form-control" placeholder="Выбранные теги" name="tags" value="[[+tags?]]" maxlength="350" id="tags"/>
            	</div>
	
    <div class="form-group">
       <textarea class="form-control" placeholder="[[%ticket_content]]" name="content" id="ticket-editor" rows="20">[[+content]]</textarea>
        <span class="error"></span>
    </div>


    <div class="ticket-form-files">
        [[+files]]
    </div>

    <div class="form-actions row">
        <div class="col-md-4">
            <input type="button" class="btn btn-default preview" value="[[%ticket_preview]]" title="Ctrl + Enter"/>
        </div>
        <div class="col-md-8 move-right">
            [[+published:is=`1`:then=`
            <a href="[[~[[+id]]?scheme=`full`]]" class="btn btn-default btn-xs" target="_blank">[[%ticket_open]]</a>
            <input type="button" class="btn btn-danger draft" name="draft" value="[[%ticket_draft]]" title=""/>
            `:else=`
            <input type="button" class="btn btn-primary publish" name="publish" value="[[%ticket_publish]]" title="" onclick="delznak();"/>
            `]]
            <input type="submit" class="btn btn-default save" name="save" value="[[%ticket_save]]"
                   title="Ctrl + Shift + Enter" onclick="delznak();"/>
            [[+allowDelete:is=`1`:then=`
                [[+deleted:is=`1`:then=`
                <input type="button" class="btn btn-default undelete" data-confirm="[[%ticket_undelete_text]]" name="undelete" value="[[%ticket_undelete]]"/>
                `:else=`
                <input type="button" class="btn btn-default delete" data-confirm="[[%ticket_delete_text]]" name="delete" value="[[%ticket_delete]]"/>
                `]]
            `]]
        </div>
    </div>
</form>



<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
<script>
tinyMCE.PluginManager.add('stylebuttons', function(editor, url) {
['pre', 'p', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach(function(name){
editor.addButton("style-" + name, {
tooltip: "Header " + name.toUpperCase(),
text: name.toUpperCase(),
onClick: function() { editor.execCommand('mceToggleFormat', false, name); },
onPostRender: function() {
var self = this, setup = function() {
editor.formatter.formatChanged(name, function(state) {
self.active(state);
});
};
editor.formatter ? setup() : editor.on('init', setup);
}
})
});
});

tinymce.init({
selector: "#ticket-editor",

content_css: "/templates/style.css", 
style_formats: [
       {title: 'Выделение синим', block: 'div', classes: 'blb'},
       {title: 'Выделение зеленым', block: 'div', classes: 'blg'},
       {title: 'Выделение красным', block: 'div', classes: 'blr'},
       {title: 'Выделение желтым', block: 'div', classes: 'blo'},
    ],
setup: function (editor) {editor.on('change', function () {editor.save();});},
plugins: ['advlist autolink lists link image charmap print preview anchor','searchreplace visualblocks code fullscreen','insertdatetime media table contextmenu paste code  stylebuttons ticketsfiles'],
advlist_bullet_styles:'',
advlist_number_styles:'',
menu:{},
toolbar:'undo redo | style-h2 style-h3 style-h4 bold blockquote italic underline strikethrough alignleft aligncenter | bullist numlist | link image styleselect visualblocks code '
});
</script>
Обратите внимание!!!
В моем случае структура: категория (обычный раздел — родитель) — подкатегория (раздел с тиккетами)
и я вывожу подкатегории, только из выбранной категории, а так как для этого — происходит обновление страницы, то до момента выбора категории, скрываю форму, чтобы пользователь не заполнил другие поля раньше времени и потерял данные.

Для чего все эти сложности. Только для одной задачи, теперь для каждого тега вы можете писать собственные: title, description и даже добавлять контент (не генерируемый автоматические, а существующий все время, а значит и индексируемый поисковиками). Это все в целом поможет привести дополнительных посетителей на сайт.
В очередной раз благодарю сообщество за подсказки, без вашей помощи никуда.
Борис И
09 июня 2016, 07:47
modx.pro
11
3 749
+7

Комментарии: 9

Павел Гвоздь
09 июня 2016, 13:31
0
Видел где-то в комментариях на сообществе эту идею. Уж не помню, кто постил.
    Борис И
    09 июня 2016, 13:34
    0
    Вот тут, но к сожалению компонент не был рожден, пришлось делать костыли.
    Федор
    10 июня 2016, 00:48
    0
    Борис, вы не могли бы показать рабочий пример? не очень понял, как это писать в ручную тайтлы? новостной сайт, тэги используются для разбивки на регионы… тоже вызов на одной странице, но как сделать, что бы заголовок страницы открывался, как не нновости по регионам. а новости «регионы из тэга». Как в вашем случае это для каждой новости нужно в ручную писать новости волгограда? что бы на странице тэгов (волгоградская область), тайтл был — новости волгограда?
      Борис И
      10 июня 2016, 08:34
      0
      Пример показать пока не смогу, сайт с тегами тестовый (рабочий в проекте). Попробую объяснить.
      Для каждого тега создается отдельная страница, соответственно для этой страницы вы можете прописать все что угодно, включая собственный title, description.
      Например у вас есть тег: Волгоград.
      По клику на данный тег пользователь попадет на отдельную страницу. Ее создаем вручную, один тег — одна страница, в доп. поле tags для этой страницы указываем «Волгоград», на этой странице будет осуществлена выборка всех ресурсов по тегу «Волгоград» с помощью вызова
      <div id="pdopage">
      	[[!+page.nav]] 
      		<div class="rows">
      			  [[!pdoPage? 			      
      			          &tpl=`tplteg`
      			          &scheme=`full`
      				  &ajaxMode=`button`
      				  &cache=`1` 
      				  &cacheTime=`86400` 
                                        &parents=`0`
                                        &resources=`-[[*id]]`
      				  &prepareTVs=`1` 
      				  &element=`pdoResources` 
      				  &includeTVs=`tags` 
      				  &limit=`10` 
      				  &hideContainers=`1` 
      				  &ajaxTplMore=`@INLINE <button class="btn btn-success btn-more">Показать еще</button>`				  
      				  &where=`{"tags:LIKE":"%[[*tags]]%"}`
      			   ]] 
      		</div>
      	[[!+page.nav]]
      </div>
      Т.е. вам понадобится столько страниц с тегами, сколько у вас городов и для каждой страницы можно будет прописать свои title, description… так как это обычная страница, просто выводит она материалы сортируя их по доп полю &where=`{«tags:LIKE»:"%[[*tags]]%"}`. Тем самым эта страница существует всегда, а не генерируется по клику пользователя и должна нормально индексироваться (как и обычные категории).
      Минус — это придется ручками создавать столько страниц, сколько тегов. Можно было бы и это автоматизировать, и автоматически создавать страницы, при прописывание статье нового тега, но на данный момент это не мой уровень знаний.
        Федор
        10 июня 2016, 14:24
        0
        ааа… да это круто! я мучался пытался сделать авто заголовки, а тут все просто. ну сделать руками каждую страницу ради такого + description получится прописать, просто супер! спасибо, буду внедрять
      Алексей
      10 июня 2016, 08:38
      +1
      Интересно, можно пойти дальше твишек, и сделать свой тип ресурсов, тэги к материалам.
      Без велосипедов, со своим ui.
        Алексей
        10 июня 2016, 08:38
        0
        Интересно, можно пойти дальше твишек, и сделать свой тип ресурсов, тэги к материалам.
        Без велосипедов, со своим ui.
          Владимир
          10 июня 2016, 08:58
          1
          +1
          дальше твишек
          Tagger -протестирован на миллионе тегов.
          Антон
          11 июня 2016, 15:19
          2
          +1
          Я у себя реализовал вот это решение (случайно нактнулся на просторах интернета):
          Система тегов: myitstuff.ru/32-tagging-site-on-modx
          Облако тегов: myitstuff.ru/36-modx-tag-cloud
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            9