Angular2 - SEO - how to manipulate the meta description

后端 未结 4 1198
野的像风
野的像风 2020-12-02 17:15

Search Results in google are displayed via TitleTag and the Tag. The </code>-Tag is editiable via Ang <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-5408099190056760" data-ad-slot="7305827575" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div> <div class="relativetags"> 相关标签: </div> </div> <div class="fly-panel detail-box" id="flyReply"> <fieldset class="layui-elem-field layui-field-title" style="text-align: center;"> <legend>4条回答</legend> </fieldset> <ul class="jieda" id="jieda"> <li data-id="111"> <a name="item-1111111111"></a> <div class="detail-about detail-about-reply"> <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-82.html"> <img src="https://www.e-learn.cn/qa/data/avatar/000/00/00/small_000000082.jpg" alt=" "> </a> <div class="fly-detail-user"> <a href="https://www.e-learn.cn/qa/u-82.html" class="fly-link"> <cite>栀梦 </cite> </a> </div> <div class="detail-hits"> <span>2020-12-02 17:49</span> </div> </div> <div class="detail-body jieda-body photos"> <p>Since Angular4, you can use Angular Meta service. </p> <pre><code>import { Meta } from '@angular/platform-browser'; // [...] constructor(private meta: Meta) {} // [...] this.meta.addTag({ name: 'robots', content: 'noindex' }); </code></pre> <div class="appendcontent"> </div> </div> <div class="jieda-reply"> <span class="jieda-zan button_agree" type="zan" data-id='731769'> <i class="iconfont icon-zan"></i> <em>0</em> </span> <span type="reply" class="showpinglun" data-id="731769"> <i class="iconfont icon-svgmoban53"></i> 讨论(0) </span> <div class="jieda-admin"> </div> </div> <div class="comments-mod " style="display: none; float:none;padding-top:10px;" id="comment_731769"> <div class="areabox clearfix"> <form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label> <div class="layui-input-block" style="margin-left:90px;"> <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" /> <input type='hidden' value='0' name='replyauthor' /> </div> <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="731769">提交评论 </span></div> </div> </form> </div> <hr> <ul class="my-comments-list nav"> <li class="loading"> <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />  加载中... </li> </ul> </div> </li> <li data-id="111"> <a name="item-1111111111"></a> <div class="detail-about detail-about-reply"> <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-25.html"> <img src="https://www.e-learn.cn/qa/data/avatar/000/00/00/small_000000025.jpg" alt=" "> </a> <div class="fly-detail-user"> <a href="https://www.e-learn.cn/qa/u-25.html" class="fly-link"> <cite>执笔经年 </cite> </a> </div> <div class="detail-hits"> <span>2020-12-02 17:51</span> </div> </div> <div class="detail-body jieda-body photos"> <p>It is possible. I implemented it in my app and below I provide the description how it is made.</p> <p>The basic idea is to use <code>Meta</code> from <code>@angular/platform-browser</code></p> <p>To dynamically change particular meta tag you have to:</p> <ol> <li>Remove the old one using <code>removeTag(attrSelector: string) : void</code> method.</li> <li>Add the new one using <code>addTag(tag: MetaDefinition, forceCreation?: boolean) : HTMLMetaElement</code> method.</li> </ol> <p>And you have to do it when the router fires route change event.</p> <p>Notice: In fact it is also necessary to have default <code><title>...</title></code> and <code><meta name="description"..." content="..."/></code> in head of index.html so before it is set dynamically there is already some static content.</p> <p>My <code>app-routing.module.ts</code> content:</p> <pre><code>import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/mergeMap'; import { NgModule } from '@angular/core'; import { RouterModule, Routes, Router, NavigationEnd, ActivatedRoute } from '@angular/router'; import { StringComparisonComponent } from '../module-string-comparison/string-comparison.component'; import { ClockCalculatorComponent } from '../module-clock-calculator/clock-calculator.component'; import { Title, Meta } from '@angular/platform-browser'; const routes: Routes = [ { path: '', redirectTo: '/string-comparison', pathMatch: 'full', data: { title: 'String comparison title', metaDescription: 'String comparison meta description content' } }, { path: 'string-comparison', component: StringComparisonComponent, data: { title: 'String comparison title', metaDescription: 'String comparison meta description content' } }, { path: 'clock-time-calculator', component: ClockCalculatorComponent, data: { title: 'Clock time calculator title', metaDescription: 'Clock time calculator meta description content' } } ]; @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule { constructor( private router: Router, private activatedRoute: ActivatedRoute, private titleService: Title, private metaService: Meta ){ //Boilerplate code to filter out only important router events and to pull out data object field from each route this.router.events .filter(event => event instanceof NavigationEnd) .map(() => this.activatedRoute) .map(route => { while (route.firstChild) route = route.firstChild; return route; }) .filter(route => route.outlet === 'primary') //Data fields are merged so we can use them directly to take title and metaDescription for each route from them .mergeMap(route => route.data) //Real action starts there .subscribe((event) => { //Changing title this.titleService.setTitle(event['title']); //Changing meta with name="description" var tag = { name: 'description', content: event['metaDescription'] }; let attributeSelector : string = 'name="description"'; this.metaService.removeTag(attributeSelector); this.metaService.addTag(tag, false); }); } } </code></pre> <ol> <li>As it can be seen there is an additional <code>data</code> object field for each route. It contains <code>title</code> and <code>metaDescription</code> strings which will be used as title and meta tag content.</li> <li>In constructor we filter out router events and we subscribe to filtered router event. Rxjs is used there, but in fact it is not necessary to use it. Regular <code>if statements</code> and <code>loops</code> could be used insead of stream, filter and map.</li> <li>We also merge our data object field with our event so we can easily use info like <code>title</code> and <code>metaDescription</code> strings.</li> <li>We dynamically change <code><title>...</title></code> and <code><meta name="description"..." content="..."/></code> tags.</li> </ol> <p>Effects:</p> <p>First component </p> <p>Second component </p> <p>In fact I currently use a little bit more sophisticated version of this solution which uses also ngx-translate to show different title and meta description for different languages.<br> Full code is available in angular2-bootstrap-translate-website-starter project.<br> The <code>app-routing.module.ts</code> file with ngx-translate solution is exactly there: app-routing.module.ts.</p> <p>There is also the production app which uses the same solution: http://www.online-utils.com.</p> <p>For sure it is not the only way and there might be better ways to do it. But I tested this solution and it works.</p> <p>In fact the solution is very similar to this from corresponding post about changing title: How to change page title in angular2 router.</p> <p>Angular Meta docs: https://angular.io/docs/ts/latest/api/platform-browser/index/Meta-class.html. In fact they aren't very informative and I had to experiment and look into real .js code to make this dynamic meta change working.</p> <div class="appendcontent"> </div> </div> <div class="jieda-reply"> <span class="jieda-zan button_agree" type="zan" data-id='731770'> <i class="iconfont icon-zan"></i> <em>0</em> </span> <span type="reply" class="showpinglun" data-id="731770"> <i class="iconfont icon-svgmoban53"></i> 讨论(0) </span> <div class="jieda-admin"> </div> </div> <div class="comments-mod " style="display: none; float:none;padding-top:10px;" id="comment_731770"> <div class="areabox clearfix"> <form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label> <div class="layui-input-block" style="margin-left:90px;"> <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" /> <input type='hidden' value='0' name='replyauthor' /> </div> <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="731770">提交评论 </span></div> </div> </form> </div> <hr> <ul class="my-comments-list nav"> <li class="loading"> <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />  加载中... </li> </ul> </div> </li> <li data-id="111"> <a name="item-1111111111"></a> <div class="detail-about detail-about-reply"> <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-102.html"> <img src="https://www.e-learn.cn/qa/data/avatar/000/00/01/small_000000102.jpg" alt=" "> </a> <div class="fly-detail-user"> <a href="https://www.e-learn.cn/qa/u-102.html" class="fly-link"> <cite>被撕碎了的回忆 </cite> </a> </div> <div class="detail-hits"> <span>2020-12-02 17:53</span> </div> </div> <div class="detail-body jieda-body photos"> <p>There is currently no out-of-the-box solution only an open issue to implement it https://github.com/angular/angular/issues/7438.</p> <p>You can of course implement something like the title service yourself, just use the TitleService as template </p> <p>A <code>Meta</code> service similar to <code>Title</code> service is in the works (currently only a pull request).</p> <div class="appendcontent"> </div> </div> <div class="jieda-reply"> <span class="jieda-zan button_agree" type="zan" data-id='731772'> <i class="iconfont icon-zan"></i> <em>0</em> </span> <span type="reply" class="showpinglun" data-id="731772"> <i class="iconfont icon-svgmoban53"></i> 讨论(0) </span> <div class="jieda-admin"> </div> </div> <div class="comments-mod " style="display: none; float:none;padding-top:10px;" id="comment_731772"> <div class="areabox clearfix"> <form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label> <div class="layui-input-block" style="margin-left:90px;"> <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" /> <input type='hidden' value='0' name='replyauthor' /> </div> <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="731772">提交评论 </span></div> </div> </form> </div> <hr> <ul class="my-comments-list nav"> <li class="loading"> <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />  加载中... </li> </ul> </div> </li> <li data-id="111"> <a name="item-1111111111"></a> <div class="detail-about detail-about-reply"> <a class="fly-avatar" href="https://www.e-learn.cn/qa/u-133.html"> <img src="https://www.e-learn.cn/qa/data/avatar/000/00/01/small_000000133.jpg" alt=" "> </a> <div class="fly-detail-user"> <a href="https://www.e-learn.cn/qa/u-133.html" class="fly-link"> <cite>隐瞒了意图╮ </cite> </a> </div> <div class="detail-hits"> <span>2020-12-02 18:01</span> </div> </div> <div class="detail-body jieda-body photos"> <p>I have developed and just released @ngx-meta/core plugin, which manipulates the meta tags at the route level, and allows setting the meta tags programmatically within the component constructor.</p> <p>You can find detailed instructions at @ngx-meta/core github repository. Also, source files might be helpful to introduce a custom logic.</p> <div class="appendcontent"> </div> </div> <div class="jieda-reply"> <span class="jieda-zan button_agree" type="zan" data-id='731771'> <i class="iconfont icon-zan"></i> <em>0</em> </span> <span type="reply" class="showpinglun" data-id="731771"> <i class="iconfont icon-svgmoban53"></i> 讨论(0) </span> <div class="jieda-admin"> </div> </div> <div class="comments-mod " style="display: none; float:none;padding-top:10px;" id="comment_731771"> <div class="areabox clearfix"> <form class="layui-form" action=""> <div class="layui-form-item"> <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label> <div class="layui-input-block" style="margin-left:90px;"> <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" /> <input type='hidden' value='0' name='replyauthor' /> </div> <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="731771">提交评论 </span></div> </div> </form> </div> <hr> <ul class="my-comments-list nav"> <li class="loading"> <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />  加载中... </li> </ul> </div> </li> <style> .laypage-main a, .laypage-main span { display: inline-block; } </style> </ul> <div class="layui-form layui-form-pane"> <form id="huidaform" name="answerForm" method="post"> <div class="layui-form-item layui-form-text"> <a name="comment"></a> <div class="layui-input-block"> <script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.config.js"></script> <script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.all.js"></script> <script type="text/plain" id="editor" name="content" style="width:100%;height:200px;"></script> <script type="text/javascript"> var isueditor=1; var editor = UE.getEditor('editor',{ //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个 toolbars:[['source','fullscreen', '|', 'undo', 'redo', '|', 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|', 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'link', 'unlink', 'anchor', '|', 'simpleupload', 'insertimage', 'scrawl', 'insertvideo', 'attachment', 'map', 'insertcode', '|', 'horizontal', '|', 'preview', 'searchreplace', 'drafts']], initialContent:'', //关闭字数统计 wordCount:false, zIndex:2, //关闭elementPath elementPathEnabled:false, //默认的编辑区域高度 initialFrameHeight:250 //更多其他参数,请参考ueditor.config.js中的配置项 //更多其他参数,请参考ueditor.config.js中的配置项 }); editor.ready(function() { editor.setDisabled(); }); $("#editor").find("*").css("max-width","362px"); </script> </div> </div> <div class="layui-form-item"> <label for="L_vercode" class="layui-form-label">验证码</label> <div class="layui-input-inline"> <input type="text" id="code" name="code" value="" required lay-verify="required" placeholder="图片验证码" autocomplete="off" class="layui-input"> </div> <div class="layui-form-mid"> <span style="color: #c00;"><img class="hand" src="https://www.e-learn.cn/qa/user/code.html" onclick="javascript:updatecode();" id="verifycode"><a class="changecode" href="javascript:updatecode();"> 看不清?</a></span> </div> </div> <div class="layui-form-item"> <input type="hidden" value="199116" id="ans_qid" name="qid"> <input type="hidden" id="tokenkey" name="tokenkey" value=''/> <input type="hidden" value="Angular2 - SEO - how to manipulate the meta description" id="ans_title" name="title"> <div class="layui-btn layui-btn-disabled" id="ajaxsubmitasnwer" >提交回复</div> </div> </form> </div> </div> <input type="hidden" value="199116" id="adopt_qid" name="qid" /> <input type="hidden" id="adopt_answer" value="0" name="aid" /> </div> <div class="layui-col-md4"> <!-- 热门讨论问题 --> <dl class="fly-panel fly-list-one"> <dt class="fly-panel-title">热议问题</dt> <!-- 本周热门讨论问题显示10条-->