Showing posts with label Blogger-Tips. Show all posts
Showing posts with label Blogger-Tips. Show all posts

Thiết kế trang báo lỗi 404 cho Blogger


404Hôm nay Blogger cập nhật thêm rất nhiều tính năng về SEO vô cùng mạnh mẽ. Đầu tiên là Meta Description tag (trước đây muốn thêm nó chúng ta phải khai báo trong template), câu lệnh tương ứng làdata:blog.metaDescription. Điều mình đánh giá cao nhất là có thể đặt Meta Description tag tương ứng trong từng bài viết, tính năng này mới giới thiệu chứ chưa thấy xuất hiện trong phần cài đặt bài viết. Tính năng thứ 2 là dễ dàng thêm rel="nofollow",target="_blank" cho thẻ liên kết. Tính năng thứ 3 là dễ dàng thêm alt, title cho ảnh. Và cuối cùng, tính năng được mong đợi từ lâu: Tạo trang báo lỗi404.

Để báo lỗi hiển thị thì template của bạn phải có hàm <b:include data='top' name='status-message'/> và hàm này phải được gọi ra. Theo mình biết thì phần lớn template hiện nay được chỉnh sửa đã xóa bỏ hàm này. Trong bài viết này mình sẽ hướng dẫn các bạn tùy chỉnh để có thể hiển thị được dòng thông báo khi không tìm thấy bài viết trong kết quả tìm kiếm và lỗi trang không tìm thấy (404). Dòng thông báo sẽ không xuất hiện khi truy cập Nhãn, Bài đăng Cũ hơn...

Thêm đoạn mã dưới đây vào sau thẻ <b:includable id='main' var='top'>trong template của bạn.
<b:if cond='data:numPosts == 0'>
 <data:navMessage/>
</b:if>

Về cơ bản đến đây là xong. Dòng thông báo chỉ xuất hiện khi số lượng bài viết trên blog bạn ở trang hiện tại là 0. Tức là khi tìm kiếm không thấy kết quả hoặc khi trang truy cập không tồn tại (404).

Để thiết kế cho trang 404 bạn vào Cài đặt → Tùy chọn tìm kiếm. Ở mục Lỗi và chuyển hướng chọn Chỉnh sửa và viết dòng thông báo bạn muốn hiển thị (hỗ trợ cả mã HTML) hoặc sử dụng đoạn mã dưới đây để hiển thị giống blog demo.
<img alt='404' width='590' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7zY5Y25Nw1yLZSmAxyVQdaM1k3IjmBch3JlLqsQZ1GgqCvrLIEv6Buox1D5HxR11WDC8qoo1-5BCLmV40loFn5lVtVnQTy3dlJO8vLJSOZUATKOBNgYkf82J3s_JNqsIJswv89KMBdc4/s590/404.png' height='399'/>

setup

Thiết kế trên đây chỉ mang tính gợi mở, hãy thể hiện sự sáng tạo của bạn trong việc thiết kế trang báo lỗi 404!

Chèn ảnh, video, nhạc vào comment Blogger


multimediaĐiểm mạnh của blog là tính tương tác giữa người viết và người đọc. Những dẫn chứng dạng chữ chưa đủ tính thuyết phục thì người đọc còn muốn chèn thêm ảnh, video hoặc nhạc. Ở diễn đàn thì việc chèn ảnh, video hay nhạc được thực hiện dễ dàng với BB code, còn Blogger chỉ hỗ trợ 3 thẻ HTML là <b>, <i> và <a> - điều đó chưa đủ làm thỏa mãn bạn? Bài viết này sẽ giúp bạn làm việc đó dễ dàng cho khung comment của Blogger.
Ảnh được chèn từ link direct còn video và nhạc thì từ Youtube và Nhaccuatui dựa vào link trên thanh địa chỉ. Code để chèn cụ thể:
  • Chèn ảnh:

    Link ảnh là http://domain.com/image.png thì code chèn sẽ là
    [img]http://domain.com/image.png[/img]
  • Chèn video từ Youtube:

    Link video là http://www.youtube.com/watch?v=0nbY7Mg_vMI&feature=related thì code chèn sẽ là
    [youtube]http://www.youtube.com/watch?v=0nbY7Mg_vMI&feature=related[/youtube]
    Link video là http://youtu.be/0nbY7Mg_vMI thì code chèn sẽ là
    [youtube]http://youtu.be/0nbY7Mg_vMI[/youtube]
  • Chèn nhạc từ Nhaccuatui:

    Link nhạc là http://www.nhaccuatui.com/nghe?L=6g3kDUIYbvmt thì code chèn sẽ là
    [nct]http://www.nhaccuatui.com/nghe?L=6g3kDUIYbvmt[/nct]
    Link nhạc là http://www.nhaccuatui.com/nghe?M=B_6M7IcZTz thì code chèn sẽ là
    [nct]http://www.nhaccuatui.com/nghe?M=B_6M7IcZTz[/nct]


Bước 1: Mở template và chèn đoạn mã dưới đây trước thẻ </body>
<b:if cond='data:blog.pageType == &quot;item&quot;'>
<script type='text/javascript'>
//<![CDATA[
function replaceText(){if(!document.getElementById){return;}
bodyText = document.getElementById("multimedia");
theText = bodyText.innerHTML;
theText = theText.replace(/\[img\].*?'.*?\[\/img\]/gi, "");
theText = theText.replace(/\[nct\].*?'.*?\[\/nct\]/gi, "");
theText = theText.replace(/\[youtube\].*?'.*?\[\/youtube\]/gi, "");
theText = theText.replace(/\[img\]/gi, "<div style='clear:both'></div><img style='float:left;margin:10px 0;border:1px solid #DDD;max-width:590px;background:#FFF;padding:4px' src='");
theText = theText.replace(/\[\/img\]/gi, "'/><div style='clear:both'></div>");
theText = theText.replace(/\[youtube\]http:\/\/youtu.be/gi, "<iframe width='480' height='390' src='http://www.youtube.com/embed");
theText = theText.replace(/\[youtube\]http:\/\/www.youtube.com\/watch\?v=/gi, "<iframe width='480' height='390' src='http://www.youtube.com/embed/");
theText = theText.replace(/&amp;feature=/gi, "?rel=0' '");
theText = theText.replace(/\[\/youtube\]/gi, "?rel=0' frameborder='0' allowfullscreen></iframe>");
theText = theText.replace(/\[nct\]http:\/\/www.nhaccuatui.com\/nghe\?L=/gi, "<div style='overflow:hidden'><embed style='margin-top:-250px;width:300px;height:400px' src='http://www.nhaccuatui.com/l/");
theText = theText.replace(/\[nct\]http:\/\/www.nhaccuatui.com\/nghe\?M=/gi, "<div style='overflow:hidden'><embed style='margin-top:-350px;width:300px;height:400px' src='http://www.nhaccuatui.com/m/");
theText = theText.replace(/\[\/nct\]/gi, "' quality='high' wmode='transparent' type='application/x-shockwave-flash'></embed></div>");
bodyText.innerHTML = theText;
}replaceText();
//]]>
</script>
</b:if>

Bước 2: Tìm thẻ <b:loop values='data:post.comments' var='comment'> và thêm trước nó thẻ <div id='multimedia'>. Tìm thẻ đóng</b:loop> và thêm sau nó thẻ </div>.

Có thể bạn muốn thêm bước 3 là hướng dẫn cho người đọc biết được cách để chèn ảnh, video và nhạc vào nhận xét? Mình để mọi người tự làm bước này.

Dễ nhận thấy thủ thuật này tương tự như bài Emoticons for Blogspot (work in IE) - Biểu tượng mặt cười cho Blogspot. Nếu bạn đã áp dụng thủ thuật đó cho blog rồi thì chỉ cần thêm đoạn mã mình đánh dấu bằng màu tím ở bước 1 vào trướcbodyText.innerHTML = theText; trong template và bỏ qua bước 2.

Blog mình không có nhu cầu chèn ảnh hay video ở comment nên không áp dụng thủ thuật này, các bạn có thể test thoải mái ở blog demo.

Đã cập nhật phiên bản mới sửa lỗi người dùng tự động thêm style, class, id làm phá vỡ bố cục của blog. Các bạn sử dụng đoạn mã mới ở bước 1.

Nexis Blogger Template - A free premium Blogger template


nexis blogger templateLựa chọn template là việc làm đầu tiên với mỗi Blogspotter. Nếu không thích những mẫu có sẵn của Blogger bạn có thể tìm thấy hàng ngàn template được chia sẻ miễn phí trên mạng. Tuy nhiên không phủ nhận là những giao diện của Wordpress luôn là niềm ao ước của nhiều Blogspotter. Hôm nay mình chia sẻ với mọi người một template với tên Nexis Blogger Templateđược thiết kế theo giao diện của Nexis Wordpress Theme.


1. Đặc điểm chính:



Header:
  • Widget Header với title (tiêu đề blog) nổi bật trên nền đỏ như một sự thay thế cho logo của blog và description (mô tả blog) nằm nhẹ nhàng bên cạnh.

    header
  • Widget PageList là menu chứa liên kết tới tới trang chủ và các trang tĩnh (static pages). Nằm ngay bên phải là hộp tìm kiếm.
  • Thanh Bookmarks gồm những liên kết mà bạn yêu thích hoặc muốn độc giả chú ý.

Main:
  • Widget Blog với bài mới nhất gồm 1 cột, các bài sau được chia làm 2 cột.

    main blog
  • Thanh địa chỉ được thêm phía trên.

    breadcrumbs
  • Sharing is sexy bookmarks được thêm ngay bên dưới bài viết.
  • Related Posts trông tương tự Wordpress.
  • Author box khiến blog chuyên nghiệp hơn.
  • Comment được thiết kế như của Wordpress và đã thêm số đếm cho comment, reply cùng bộ emoticons ngộ nghĩnh. Ghi chú Author được làm nổi bật bên cạnh tên tác giả bài viết ở phần comment, xem thêm hướng dẫn tại đây.

Bài viết liên quan cho Blogger - Related posts

Bài viết liên quan cho Blogger - Related posts

related posts for blogger
Trước đây mình có giới thiệu bài Tạo bài viết liên quan theo nhãn được viết bởihoctro.blogspot.com tuy nhiên thủ thuật này có nhược điểm là lỗi hiển thị với tên nhãn Tiếng Việt và vẫn hiển thị tên bài đang xem ở danh sách bài viết liên quan. Thủ thuật mình giới thiệu sau đây sẽ khắc phục 2 nhược điểm đó. Thủ thuật này được phát triển bởi một blogger người Ấn Độ tại địa chỉ Way2Blogging và mình có thêm tính năng hiển thị ngày tháng đăng bài khi đưa chuột vào tên bài viết.


Bước 1: Thêm đoạn mã dưới đây vào trước thẻ </head>
<b:if cond='data:blog.pageType == &quot;item&quot;'>
<script type="text/javascript">
//<![CDATA[
var titles=new Array();var titlesNum=0;var urls=new Array();var time=new Array();function related_results_labels(c){for(var b=0;b<c.feed.entry.length;b++){var d=c.feed.entry[b];titles[titlesNum]=d.title.$t;for(var a=0;a<d.link.length;a++){if(d.link[a].rel=="alternate"){urls[titlesNum]=d.link[a].href;time[titlesNum]=d.published.$t;titlesNum++;break}}}}function removeRelatedDuplicates(){var b=new Array(0);var c=new Array(0);e=new Array(0);for(var a=0;a<urls.length;a++){if(!contains(b,urls[a])){b.length+=1;b[b.length-1]=urls[a];c.length+=1;c[c.length-1]=titles[a];e.length+=1;e[e.length-1]=time[a]}}titles=c;urls=b;time=e}function contains(b,d){for(var c=0;c<b.length;c++){if(b[c]==d){return true}}return false}function printRelatedLabels(a){var y=a.indexOf('?m=0');if(y!=-1){a=a.replace(/\?m=0/g,'')}for(var b=0;b<urls.length;b++){if(urls[b]==a){urls.splice(b,1);titles.splice(b,1);time.splice(b,1)}}var c=Math.floor((titles.length-1)*Math.random());var b=0;document.write("<ul>");if(titles.length==0){document.write("<li>Không có bài viết liên quan</li>")}else{while(b<titles.length&&b<20&&b<maxresults){if(y!=-1){urls[c]=urls[c]+'?m=0'}document.write('<li><a href="'+urls[c]+'" title="'+time[c].substring(8,10)+"/"+time[c].substring(5,7)+"/"+time[c].substring(0,4)+'">'+titles[c]+"</a></li>");if(c<titles.length-1){c++}else{c=0}b++}}document.write("</ul>");urls.splice(0,urls.length);titles.splice(0,titles.length)};
//]]>
</script>
</b:if>
Update 05/06/2011: Đoạn mã ở bước 1 mình đã thêm tính năng hiển thị thông báo khi không có bài viết liên quan và sửa lỗi hiển thị sai thời gian khi xem bài viết liên quan ở bài viết có hơn 2 nhãn.

Bước 2: Bài viết liên quan thường được hiển thị bên dưới mỗi bài viết. Trong template của Blogger thì những tiện ích đặt bên dưới mỗi bài viết thường nằm trong cặp thẻ <div class='post-footer'></div>. Thêm đoạn mã dưới đây vào bên trong cặp thẻ<div class='post-footer'></div> ở template của bạn.
<b:if cond='data:blog.pageType == &quot;item&quot;'>
    <div id='related-posts'>
        <b>Bài viết liên quan:</b>
        <b:loop values='data:post.labels' var='label'>
            <script expr:src='&quot;/feeds/posts/default/-/&quot; + data:label.name + &quot;?alt=json-in-script&amp;callback=related_results_labels&quot;' type='text/javascript'/>
        </b:loop>
        <script type='text/javascript'>var maxresults=5;removeRelatedDuplicates();printRelatedLabels('<data:post.url/>');</script>
    </div>
</b:if>
Tham khảo hình dưới đây:



maxresults là số bài viết hiển thị ở danh sách bài viết liên quan. Thủ thuật này đặt giá trị là 5, bạn có thể thay đổi theo ý muốn.

Giống như thủ thuật Bài viết mới hay Nhận xét mới, thủ thuật Bài viết liên quan này cũng lấy dữ liệu từ nguồn feed và dùng hàm document.write để hiển thị. Nhược điểm là không cải thiện thêm về SEO vì các bộ máy tìm kiếm bỏ qua không đọc tới hàmdocument.write này.

Emoticons for Blogspot (work in IE) - Biểu tượng mặt cười cho Blogspot


Emoticons for Blogspot (work in IE)Blogspot luôn bị so sánh với Wordpress bởi đây là 2 nền tảng blog hàng đầu hiện nay. Ngoài khả năng SEO như mình đề cập đến trong bài trước thì hệ thống Nhận xét của blogspot cũng bị chê bai rất nhiều và điều nhận thấy rõ nhất là hiện nay một số blogger đã chuyển sang dùng Nhận xét bên ngoài như của Disqus, IntenseDebate... Lý do có lẽ là việc reply lại Nhận xét trên blogspot khó khăn và không trực quan như Wordpress, đến giờ cũng chỉ hiển thị được avatar cho tài khoản Google, không chỉnh sửa được khung Đăng Nhận xét...Khung Đăng Nhận xét của blogspot là một trang riêng được chèn vào blog thông qua thẻ iframe và Google không cho ta quyền can thiệp vào khung Đăng Nhận xét này. Đó là lý do mà không đưa được bộ gõ riêng cũng như emoticons vào khung Đăng Nhận xét. Với bộ gõ thì dường như không thể cho đến khi nào Google tích hợp thêm vào. Còn với emoticons thì thật may là có hàm replace, sử dụng hàm này để thay đổi ký tự thành hình ảnh và blogspot đã có emoticons cho dù việc nhập emoticons không thể theo kiểu click.Emoticons cho blogspot đã được giới thiệu khá lâu rồi, trong bài này mình sẽ hướng dẫn các bạn tạo emoticons cho khung Nhận xét sao cho hiển thị được cả trên các phiên bản trình duyệtInternet Explorer (IE).Bước 1: Mở template và chèn đoạn mã dưới đây trước thẻ </body>
<script type='text/javascript'>
//<![CDATA[
function replaceText(){if(!document.getElementById){return;}
bodyText = document.getElementById("emocomments");
theText = bodyText.innerHTML;
theText = theText.replace(/:\)\)/gi, "<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vt_XVZKI/AAAAAAAAATI/Q35_W0anT6A/21.gif'/>");
theText = theText.replace(/=d&gt;/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vzUt1yQI/AAAAAAAAATY/QHNvnj0gYbU/41.gif'/>");
theText = theText.replace(/:d/gi, "<img src='http://lh3.ggpht.com/_u7a1IFxc4WI/TM-voxnkRKI/AAAAAAAAAS4/PjDn098vm3w/4.gif'/>");
theText = theText.replace(/:p/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vpDb68dI/AAAAAAAAAS8/Yv0Uu3qzG_Q/10.gif'/>");
theText = theText.replace(/:\(\(/gi, "<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vt5z16MI/AAAAAAAAATE/Hx-7Thmr6do/20.gif'/>");
theText = theText.replace(/:\)/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-voiNIw2I/AAAAAAAAASw/aav2hwqeG0c/1.gif'/>");
theText = theText.replace(/:\(/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-voq7QQnI/AAAAAAAAAS0/UzoFJOCcPPU/2.gif'/>");
theText = theText.replace(/:-\?/gi, "<img src='http://lh5.ggpht.com/_u7a1IFxc4WI/TM-vua5MF2I/AAAAAAAAATU/N4X-ouMd1-I/39.gif'/>");
theText = theText.replace(/\[\-\(/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vuMg6RQI/AAAAAAAAATQ/rWj7euuKOZs/33.gif'/>");
theText = theText.replace(/:-o/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vpLiW1GI/AAAAAAAAATA/fPyPJcBks7s/13.gif'/>");
theText = theText.replace(/:-t/gi, "<img src='http://lh3.ggpht.com/_u7a1IFxc4WI/TM-vz4hwcNI/AAAAAAAAATo/4ySXuvQWma8/104.gif'/>");
theText = theText.replace(/:-ss/gi, "<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vzUOH79I/AAAAAAAAATc/oNE5H5vcNtI/42.gif'/>");
theText = theText.replace(/b-\(/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vzrqI4MI/AAAAAAAAATk/BhfFnT0Gbro/66.gif'/>");
theText = theText.replace(/@-\)/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vziH8NXI/AAAAAAAAATg/2evEbN2cJwc/43.gif'/>");
theText = theText.replace(/=\)\)/gi, "<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vuJ1G41I/AAAAAAAAATM/_jLHXvz6PTg/24.gif'/>");
bodyText.innerHTML = theText;
}replaceText();
//]]>
</script>
Bước 2: Tìm đến thẻ <b:loop values='data:post.comments' var='comment'> và thêm trước nó thẻ <div id='emocomments'>. Tìm thẻ đóng</b:loop> và thêm sau nó thẻ </div>.

Bước 3: Bước này là hiển thị những ký tự tắt và emoticons tương ứng với nó cho người đọc có thể biết được để chèn vào khung Nhận xét.

Emoticons for Blogspot (work in IE)


Tìm đến thẻ <data:blogTeamBlogMessage/> thứ 2 và chèn đoạn mã dưới đây vào sau nó:
<script type="text/javascript"> 
//<![CDATA[
function moreSmilies() {
    document.getElementById('smiley-more').style.display = 'inline';
    document.getElementById('smiley-toggle').innerHTML = '<a href="javascript:lessSmilies()">&#8592;</a></span>';
}
function lessSmilies() {
    document.getElementById('smiley-more').style.display = 'none';
    document.getElementById('smiley-toggle').innerHTML = '<a href="javascript:moreSmilies()">&#8594;</a>';
}
//]]>
</script>
<div class='emoticons'>
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-voiNIw2I/AAAAAAAAASw/aav2hwqeG0c/1.gif'/>:) 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-voq7QQnI/AAAAAAAAAS0/UzoFJOCcPPU/2.gif'/>:( 
<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vt_XVZKI/AAAAAAAAATI/Q35_W0anT6A/21.gif'/>:)) 
<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vt5z16MI/AAAAAAAAATE/Hx-7Thmr6do/20.gif'/>:(( 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vuJ1G41I/AAAAAAAAATM/_jLHXvz6PTg/24.gif'/>=)) 
<span id='smiley-more' style='display: none;'>
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vzUt1yQI/AAAAAAAAATY/QHNvnj0gYbU/41.gif'/>=D&gt; 
<img src='http://lh3.ggpht.com/_u7a1IFxc4WI/TM-voxnkRKI/AAAAAAAAAS4/PjDn098vm3w/4.gif'/>:D 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vpDb68dI/AAAAAAAAAS8/Yv0Uu3qzG_Q/10.gif'/>:P 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vpLiW1GI/AAAAAAAAATA/fPyPJcBks7s/13.gif'/>:-O 
<img src='http://lh5.ggpht.com/_u7a1IFxc4WI/TM-vua5MF2I/AAAAAAAAATU/N4X-ouMd1-I/39.gif'/>:-? 
<img src='http://lh4.ggpht.com/_u7a1IFxc4WI/TM-vzUOH79I/AAAAAAAAATc/oNE5H5vcNtI/42.gif'/>:-SS 
<img src='http://lh3.ggpht.com/_u7a1IFxc4WI/TM-vz4hwcNI/AAAAAAAAATo/4ySXuvQWma8/104.gif'/>:-t 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vuMg6RQI/AAAAAAAAATQ/rWj7euuKOZs/33.gif'/>[-( 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vziH8NXI/AAAAAAAAATg/2evEbN2cJwc/43.gif'/>@-) 
<img src='http://lh6.ggpht.com/_u7a1IFxc4WI/TM-vzrqI4MI/AAAAAAAAATk/BhfFnT0Gbro/66.gif'/>b-(
</span>
<span id='smiley-toggle'><a href="javascript:moreSmilies()">&#8594;</a></span>
</div>
Thêm một class emoticons. Chèn đoạn mã dưới vào trước thẻ ]]></b:skin>
.emoticons {-moz-background-clip: -moz-initial;-moz-background-origin: -moz-initial;-moz-background-inline-policy: -moz-initial;text-align: left;}
.emoticons a, .emoticons a:hover {font-size: 28px;margin-left: 20px;text-decoration:none;}


Mở rộng:


Các bước trên là chèn 15 emoticons của Zing với ký tự tắt theo phong cách Yahoo. Bạn hoàn toàn có thể thêm emoticons mới nữa và tự đặt ký tự tắt theo ý mình bằng cách chỉnh sửa code javascript ở bước 1.

Ký tự tắt nằm giữa 2 ký tự /
  • Với ký tự đặc biệt như [ ] { } \ / ( ) . ? + * ^ $ thì phải thêm \ trước nó.
  • Với ký tự < phải đổi thành &lt;
  • Với ký tự > phải đổi thành &gt;
  • Với ký tự & phải đổi thành &amp;
Hình ảnh emoticons nằm trong thẻ img, thay đường dẫn đến ảnh tương ứng với ký tự tắt mà bạn đặt.

Lưu ý là với những ký tự tắt bao gồm của nhau như :)) và :) thì bạn phải đặt :)) lên trước:) nếu không chỉ ký tự ít hơn được hiện lên.

Nếu không muốn hiển thị những Nhận xét dung tục ta khai báo những ký tự đó và thay tương ứng không phải là thẻ img nữa mà là ký tự *** chẳng hạn.

Sau khi đã thành công với việc chèn emoticons vào khung Nhận xét bạn hoàn toàn có thể chèn emoticons vào khung Bài đăng hay khung Nhận xét mới bằng cách tạo một ID mới bao quanh khung Bài đăng hay khung Nhận xét mới và khai báo ID này trong javascript ở bước 1 tương tự như khai báo ID emocomments (tên ID phải khác nhau).

Vì không thể chèn emoticons theo kiểu click do đó chúng ta chỉ nên sử dụng những ký tự tắt thông dụng để không gây khó khăn cho người đọc.

Cũng đừng nên tham lam chèn nhiều emoticons dẫn đến trình duyệt phải xử lý nhiều thông tin khiến blog tải chậm hơn.

Giờ thì khách thăm blog của bạn thoải mái Nhận xét với những emoticon ngộ nghĩnh cho dù họ có đang dùng trình duyệt bị giới web development ghét nhất mang tên IE 6.

Cảm ơn Noct đã giúp sửa lỗi không hiển thị avatar của tài khoản Blogger.

Nếu bạn đang sử dụng comment phân cấp của Tien Nguyen thì thay thế emocommentsở đoạn mã bước 1 thành cm_block và bỏ qua bước 2.

All in One SEO Pack cho Blogspot

Điểm thua thiệt lớn nhất của Blogspot so với Wordpress là khả năng SEO cho dù Blogspot là đứa con của Google - ông lớn trong làng tìm kiếm.


Vậy tại sao khả năng SEO của Blogspot lại không bằng Wordpress? Wordpress có thẻ tags còn với Blogspot thì không.


meta tag


Nhân đọc bài Hướng dẫn cài "All in One SEO Pack" cho Blogspot/Blogger.com của Minh Mèothấy tác giả làm khá thủ công. Blogspot có thẻ <data:blog.pageName> để hiển thị tiêu đề trang của blog nên mình có ý lấy thẻ này để gọi tiêu đề trang và đưa vào Meta tag. Với cách làm này thì mỗi trang sẽ có thẻ Meta tag riêng mô tả và được lấy tự động theo tiêu đề trang của blog.


Tìm trong template đoạn mã:
<title><data:blog.title/></title>
<b:if cond='data:blog.metaDescription != &quot;&quot;'>
 <meta expr:content='data:blog.metaDescription' name='description'/>
</b:if>

Thay thế nó bằng đoạn mã dưới đây:
<b:if cond='data:blog.pageTitle == data:blog.title'>
 <title><data:blog.title/></title>
<b:else/>
 <title><data:blog.pageName/> | <data:blog.title/></title>
</b:if>
<b:if cond='data:blog.metaDescription != &quot;&quot;'>
 <meta expr:content='data:blog.metaDescription' name='description'/>
</b:if>
<b:if cond='data:blog.pageType == &quot;archive&quot;'>
 <meta content='noindex, nofollow' name='robots'/>
<b:else/>
 <b:if cond='data:blog.pageType == &quot;index&quot;'>
  <b:if cond='data:blog.url == data:blog.homepageUrl'>
   <meta expr:content='data:blog.title' name='keywords'/>
   <meta content='index, follow' name='robots'/>
  </b:if>
 <b:else/>
  <b:if cond='data:blog.pageTitle != data:blog.title'>
   <meta expr:content='data:blog.pageName' name='keywords'/>
   <meta content='index, follow' name='robots'/>
  </b:if>
 </b:if>
</b:if>

Cách làm trên cũng đã đưa tiêu đề của Bài đăng lên trước tiêu đề của blog.

Trong lần cập nhật này đoạn mã được thay đổi để phù hợp với tính năng thêm Meta Description tag của Blogger, xem thêm hướng dẫn tại đây. Tiêu đề trang rõ ràng và hợp lý hơn trong từng trường hợp. Chặn bot tìm kiếm ở kiểu trang lưu trữ, việc chặn này chỉ là để không bị đưa vào sitelinks chứ không phải mục đính tránh trùng lặp nội dung do Blogger đã có readmore (tất nhiên không tính auto readmore viết bằng javascript). Cùng với đó chỉ thêm keywords và cho bot tìm kiếm ở 3 kiểu trang: Trang chủ, Bài viết và Trang tĩnh. Đây là 3 kiểu trang được Google lập chỉ mục.

Thêm chú thích cho nhận xét của tác giả bài viết

Việc thêm ghi chú cho nhận xét của tác giả bài viết là chủ đề không mới nhưng thực sự những thủ thuật về nó ở một số blog, thậm chí blog nổi tiếng về templates và thủ thuật Blogger như chethstudios cũng mắc phải sai lầm khi dùng điều kiện so sánh <b:if cond='data:comment.author == data:post.author'>


data:comment.author là tên người nhận xét, data:post.author là tên người viết bài, nếu giống nhau sẽ thực hiện lệnh bên trong. Như vậy với tên người nhận xét chỉ cần giống tên người viết bài thì lệnh so sánh trên được thực hiện.

Blogger XML code cung cấp cho chúng ta một số "định nghĩa" về người quản trị blog trong đódata:comment.adminClass là dữ liệu về nhận xét của người quản trị blog,data:post.adminClass là dữ liệu về người viết bài. Như vậy thay vì dùng lệnh điều kiện so sánh tên chúng ta sẽ so sánh dữ liệu của người nhận xét và người viết bài xem có giống nhau không. Ở đây mình sẽ hướng dẫn các bạn thêm ghi chú Tác giả bài viết sau tên nhận xét của người viết bài.

1. Tìm trong template của bạn đoạn mã <a expr:href='data:comment.authorUrl' rel='nofollow'><data:comment.author/></a>. Đoạn mã trên là hiển thị tên người nhận xét có liên kết tới địa chỉ profile của người đó (cần chú ý là không phải template nào đoạn mã trên cũng y nguyên như vậy, nó có thể thêm vài thuộc tính trong cặp thẻ <a></a> này). Thêm đoạn mã dưới đây vào sau nó:
<b:if cond='data:comment.adminClass == data:post.adminClass'>
 <span class='author-comment'>Tác giả bài viết</span>
</b:if>

2. Thêm một class author-comment quy định màu cho chữ Tác giả bài viết. Thêm đoạn mã dưới đây vào trước thẻ ]]></b:skin> trong template của bạn:
.author-comment{background:#FF0000;padding:0 3px;color:#FFF}

Chữ Tác giả bài viết với màu trắng trên nền đỏ được hiển thị bên cạnh tên nhận xét của người viết bài, đây là cách đơn giản nhất để tạo sự khác biệt cho nhận xét của tác giả bài viết với các nhận xét còn lại. Có thể tùy biến thêm với lệnh <b:if cond='data:comment.adminClass == data:post.adminClass'> cho những thành phần khác của nhận xét như màu nền để tạo thêm sự khác biệt.

3. Nếu blog có nhiều người viết bài có lẽ bạn muốn thêm ghi chú Admin sau tên nhận xét của mình nữa. Để làm được điều này chúng ta sẽ dùng lệnh so sánh địa chỉ profile của người nhận xét. Thêm đoạn mã dưới đây vào trước đoạn mã ở bước 1:
<b:if cond='data:comment.authorClass == &quot;blog-author&quot;'>
 <b:if cond='data:comment.authorUrl == &quot;http://www.blogger.com/profile/14698901063970946455&quot;'>
  <span class='author-comment'>Admin</span>
 </b:if>
</b:if>

Nhớ thay http://www.blogger.com/profile/14698901063970946455thành địa chỉ profile của bạn.

<b:if cond='data:comment.adminClass == data:post.adminClass'> là lệnh rất hay, các bạn có thể thử nghiệm cho dù tên 2 người quản trị có giống nhau thì lệnh so sánh trên vẫn hoạt động đúng.

Tùy biến thêm lệnh so sánh profile ở phần 3 để thêm ghi chú Author sau tên nhận xét của những người cộng tác viết bài trên blog của bạn.

Recent Google Plus và Recent Twitter cho Blogger


google plus twitterGoogle Plus và Twitter là những mạng xã hội phổ biến nhất hiện nay, đây là mảnh đất tốt cho nhiều người quảng bá Website/Blog, vì vậy có nhiều thủ thuật liên quan tới những mạng xã hội này. Trong bài viết này mình hướng dẫn các bạn tạo widget hiển thị nội dung những bài viết mới nhất trên Google Plus và Twitter để đưa vào blog.

1. Recent Google Plus:


Bước 1: Xác định ID tài khoản Google Plus của bạn. Ví dụ: 115601584709388240037

Bước 2: Từ ID Google Plus ta có link:
http://plusfeed2.appspot.com/115601584709388240037

Bước 3:
  • Thêm 1 widget Nguồn cấp tại nơi muốn hiển thị Recent Google Plus. Dán link ở bước 2 vào URL nguồn cấp và nhấn TIẾP TỤC.

    widget feed url
  • Ở cửa sổ tiếp theo hiệu chỉnh Tiêu đề và Hiển thị theo ý bạn rồi chọn LƯU.

    widget feed edit


2. Recent Twitter:


Thêm 1 widget HTML/Javascript tại nơi muốn hiển thị Recent Twitter. Hiệu chỉnh Tiêu đề và dán đoạn mã dưới đây vào phần Nội dung rồi chọn LƯU.
<script style='text/javascript'>
function rtw(tw){var statusHTML=[];twstr=70;document.write('<ul>');for(var i=0;i<tw.length;i++){var text=tw[i].text;if(text.length>twstr){var textstr=text.lastIndexOf(' ');text=text.substring(0,textstr)+'&#133;'};document.write('<li><a href="http://twitter.com/'+tw[i].user.screen_name+'/statuses/'+tw[i].id_str+'" rel="nofollow" target="_blank">'+text+'</a></li>')};document.write('</ul>');};
</script>
<script src='http://twitter.com/statuses/user_timeline/duyphaminfo.json?count=5&amp;callback=rtw' type='text/javascript'/></script>

Thay duyphaminfo thành tên tài khoản Twitter của bạn.

Phần hiển thị là theo kiểu danh sách <li> và thường đã khai báo trong CSS, nếu muốn chi tiết hơn bạn tự thiết kế theo phong cách riêng của mỗi người.

CSS3 for web designers

css3 for web designersMột cuốn sách của Dan Cederholm. Đúng như tên gọi, cuốn sách hướng nhiều về việc sử dụng CSS3 trong việc thiết kế. Thông qua những ví dụ trực quan với các bước làm cùng hướng dẫn bạn sẽ biết được cách tạo navigation; button; form; các hiệu ứng xoay, thay đổi kích thước, làm mờ ảnh... Lồng trong những ví dụ đó là cách sử dụng border-radius, text-shadow, box-shadow, RGBA... và không quên hướng dẫn dùng cho từng trình duyệt khác nhau.

Trực quan và dễ hiểu, đây là cuốn sách cần thiết cho những người bắt đầu làm quen với CSS3. 

Cuốn sách có giá bán là 9$. Liên kết sẽ bị xóa nếu tác giả yêu cầu!

Bài viết liên quan có hình ảnh cho Blogger


related postsKhi đặt bút viết bài này (chính xác hơn là đặt tay lên bàn phím) mình băn khoăn không biết có nên viết không. Đây là chủ đề không mới và có thể 1 số bạn không xem xét kỹ code mà chỉ lướt qua tiêu đề rồi cho rằng mình lấy code ở 1 nơi khác rồi xào lại. Ở bài Bài viết liên quan cho Blogger - Related Posts mình có nói thủ thuật được phát triển bởi một blogger người Ấn Độ. Thực ra code ban đầu mình xem ở 1 template tại Btemplates và nó có nhược điểm là vẫn hiển thị tên bài đang xem ở danh sách bài viết liên quan. Khi tình cờ vào blog của Harish mình để ý thấy lỗi này đã được fix và mình cho rằng Harish đã sửa được lỗi đó. Tuy nhiên blog này có viết bài về phân trang và sử dụng code của Abu Farhan nhưng đề bản quyền bởi Harish thì mình tự hỏi điều tương tự có xảy ra với Related Posts?

Quay lại bài viết này. Khi chưa có widget Popular Posts thì ảnh ở feed có kích thước với ảnh trên blog nên mình không quan tâm đến Related Posts with thumbnails vì cho rằng nó làm giảm tốc độ của blog. Hiện nay ảnh ở đây có kích thước 72x72 pixels, vấn đề dung lượng không còn quan trọng và mình bắt đầu thêm hiển thị ảnh. Khi test với bài viết có hơn 2 nhãn mình mới phát hiện ra hình ảnh không còn đúng với bài viết, nguyên nhân do chưa khai báo biến này trong hàm removeRelatedDuplicates (đây là hàm loại bỏ nội dung trùng lặp, khi mà 1 bài viết xuất hiện ở 2 nhãn). Như vậy ở bài Bài viết liên quan cho Blogger - Related Posts lâu nay đã bị lỗi hiển thị ngày tháng đăng bài khi ở bài viết gắn với hơn 1 nhãn. Qua bài viết này mình cũng muốn thông báo và xin lỗi đến những bạn đã áp dụng thủ thuật đó, mình đã update lại code.

Những thủ thuật mình giới thiệu nếu chủ đề không mới thì có nghĩa mình đã thêm một vài tính năng nào đó, Related Posts with thumbnails cũng vậy. Thừa hưởng từ thủ thuật trước là loại bỏ bài viết đang xem ở danh sách bài viết liên quan thì ở bản này mình thêm hình ảnh, ngày tháng đăng bài và số lượng comments trong bài viết đó, đây là những thông tin mà mình cảm thấy cần thiết. Ngoài ra thì mình có thêm 2 tính năng nữa là hiển thị thông báo không có bài viết liên quan (điều này xảy ra khi trong 1 nhãn chỉ có 1 bài viết và bài viết đó cũng chỉ gắn với 1 nhãn) và lựa chọn có hiển thị số lượng comments hay không (dành cho blog chỉ đơn giản như 1 trang tin và không bật commnet hoặc là blog không sử dụng comment mặc định của Blogger).

Ở đây mình giới thiệu 2 kiểu là hiển thị theo hàng dọc và hiển thị theo hàng ngang.

1. Hiển thị Related Posts theo hàng dọc.



related posts thumbnails style 1

  • Bước 1: Thêm đoạn mã dưới đây vào trước thẻ ]]></b:skin> trong template của bạn.
    #related-posts{float:left}
    #related-posts ul{margin:0;padding:0;list-style-type:none}
    #related-posts ul li{padding:10px 0}
    #related-posts ul li:hover img{width:42px;height:42px;padding:0}
    #related-posts img{float:left;border:1px solid #BBB;margin-right:10px;width:36px;height:36px;background:#FFF;padding:3px}
    #related-posts h3{margin:0;font-size:16px}
  • Bước 2: Thêm đoạn mã dưới đây vào sau thẻ <div class='post-footer'>trong template của bạn.
    <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <div style='clear:both'/>
    <div id='related-posts'>
    <script type='text/javascript'>var ry='<h2>Bài viết liên quan</h2>';rn='<h2>Không có Bài viết liên quan</h2>';rcomment='Nhận xét';rdisable='Tắt Nhận xét';commentYN='yes';</script>
    <script type='text/javascript'>
    //<![CDATA[
    var dw='';titles=new Array();titlesNum=0;urls=new Array();timeR=new Array();thumb=new Array();commentsNum=new Array();comments=new Array();function related_results_labels(c){for(var b=0;b<c.feed.entry.length;b++){var d=c.feed.entry[b];titles[titlesNum]=d.title.$t;for(var a=0;a<d.link.length;a++){if('thr$total' in d){commentsNum[titlesNum]=d.thr$total.$t+' '+rcomment}else{commentsNum[titlesNum]=rdisable};if(d.link[a].rel=="alternate"){urls[titlesNum]=d.link[a].href;timeR[titlesNum]=d.published.$t;if('media$thumbnail' in d){thumb[titlesNum]=d.media$thumbnail.url}else{thumb[titlesNum]='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq9XOemOISGkIrdBs12hLJ-WWws_KOs9r6QxZDrbJfz4fY2YC5HZ_2lC1YsGmF6_BoTBRr-W5vAtFOh2B4xY7uiTgbmhILhAq-YfZnI34jamd1oBsMzzQFm1Wykd2QdfBoR5XIGa2qD48Z/'};titlesNum++;break}}}}function removeRelatedDuplicates(){var b=new Array(0);c=new Array(0);e=new Array(0);f=new Array(0);g=new Array(0);for(var a=0;a<urls.length;a++){if(!contains(b,urls[a])){b.length+=1;b[b.length-1]=urls[a];c.length+=1;c[c.length-1]=titles[a];e.length+=1;e[e.length-1]=timeR[a];f.length+=1;f[f.length-1]=thumb[a];g.length+=1;g[g.length-1]=commentsNum[a]}}urls=b;titles=c;timeR=e;thumb=f;commentsNum=g}function contains(b,d){for(var c=0;c<b.length;c++){if(b[c]==d){return true}}return false}function printRelatedLabels(a){var y=a.indexOf('?m=0');if(y!=-1){a=a.replace(/\?m=0/g,'')}for(var b=0;b<urls.length;b++){if(urls[b]==a){urls.splice(b,1);titles.splice(b,1);timeR.splice(b,1);thumb.splice(b,1);commentsNum.splice(b,1)}}var c=Math.floor((titles.length-1)*Math.random());var b=0;if(titles.length==0){dw+=rn}else{dw+=ry;dw+='<ul>';while(b<titles.length&&b<20&&b<maxresults){if(y!=-1){urls[c]=urls[c]+'?m=0'}if(commentYN=='yes'){comments[c]=' - '+commentsNum[c]}else{comments[c]=''};dw+='<li><img alt="'+titles[c]+'" src="'+thumb[c]+'"/><div><h3><a href="'+urls[c]+'" rel="nofollow">'+titles[c]+'</a></h3><span>'+timeR[c].substring(8,10)+'/'+timeR[c].substring(5,7)+'/'+timeR[c].substring(0,4)+comments[c]+'</span></div></li><div style="clear:both"></div>';if(c<titles.length-1){c++}else{c=0}b++}dw+='</ul>'};urls.splice(0,urls.length);titles.splice(0,titles.length);document.getElementById('related-posts').innerHTML=dw};
    //]]>
    </script>
    <b:loop values='data:post.labels' var='label'>
    <script expr:src='&quot;/feeds/posts/default/-/&quot; + data:label.name + &quot;?alt=json-in-script&amp;callback=related_results_labels&quot;' type='text/javascript'/>
    </b:loop>
    <script type='text/javascript'>var maxresults=6;removeRelatedDuplicates();printRelatedLabels('<data:post.url/>');</script>
    </div>
    <div style='clear:both'/>
    </b:if>

2. Hiển thị Related Posts theo hàng ngang.



related posts thumbnails style 2

  • Bước 1: Thêm đoạn mã dưới đây vào trước thẻ ]]></b:skin> trong template của bạn.
    #related-posts{float:left}
    #related-posts ul{margin:5px 0;width:524px;padding:0;list-style-type:none}
    #related-posts ul li{position:relative;float:left;border:0 none;margin-right:11px;width:76px}
    #related-posts ul li:hover{z-index:98}
    #related-posts ul li:hover img{border:3px solid #BBB}
    #related-posts ul li:hover div{position:absolute;top:40px;left:10px;margin-left:0;width:200px}
    #related-posts ul li img{border:3px solid #DDD;width:70px;height:70px;background:#FFF}
    #related-posts ul li div{position:absolute;z-index:99;margin-left:-999em}
    #related-posts ul li .title{border:1px solid #CCC;background:#FFF;padding:5px 10px}
  • Bước 2: Thêm đoạn mã dưới đây vào sau thẻ <div class='post-footer'>trong template của bạn.
    <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <div style='clear:both'/>
    <div id='related-posts'>
    <script type='text/javascript'>var ry='<h2>Bài viết liên quan</h2>';rn='<h2>Không có Bài viết liên quan</h2>';rcomment='Nhận xét';rdisable='Tắt Nhận xét';commentYN='yes';</script>
    <script type='text/javascript'>
    //<![CDATA[
    var nothumb='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq9XOemOISGkIrdBs12hLJ-WWws_KOs9r6QxZDrbJfz4fY2YC5HZ_2lC1YsGmF6_BoTBRr-W5vAtFOh2B4xY7uiTgbmhILhAq-YfZnI34jamd1oBsMzzQFm1Wykd2QdfBoR5XIGa2qD48Z/';dw='';titles=new Array();titlesNum=0;urls=new Array();time=new Array();thumb=new Array();commentsNum=new Array();comments=new Array();function related_results_labels(c){for(var b=0;b<c.feed.entry.length;b++){var d=c.feed.entry[b];titles[titlesNum]=d.title.$t;for(var a=0;a<d.link.length;a++){if('thr$total' in d){commentsNum[titlesNum]=d.thr$total.$t+' '+rcomment}else{commentsNum[titlesNum]=rdisable};if(d.link[a].rel=="alternate"){urls[titlesNum]=d.link[a].href;time[titlesNum]=d.published.$t;if('media$thumbnail' in d){thumb[titlesNum]=d.media$thumbnail.url}else{thumb[titlesNum]=nothumb};titlesNum++;break}}}}function removeRelatedDuplicates(){var b=new Array(0);c=new Array(0);e=new Array(0);f=new Array(0);g=new Array(0);for(var a=0;a<urls.length;a++){if(!contains(b,urls[a])){b.length+=1;b[b.length-1]=urls[a];c.length+=1;c[c.length-1]=titles[a];e.length+=1;e[e.length-1]=time[a];f.length+=1;f[f.length-1]=thumb[a];g.length+=1;g[g.length-1]=commentsNum[a]}}urls=b;titles=c;time=e;thumb=f;commentsNum=g}function contains(b,d){for(var c=0;c<b.length;c++){if(b[c]==d){return true}}return false}function printRelatedLabels(a){var y=a.indexOf('?m=0');if(y!=-1){a=a.replace(/\?m=0/g,'')}for(var b=0;b<urls.length;b++){if(urls[b]==a){urls.splice(b,1);titles.splice(b,1);time.splice(b,1);thumb.splice(b,1);commentsNum.splice(b,1)}}var c=Math.floor((titles.length-1)*Math.random());var b=0;if(titles.length==0){dw+=rn}else{dw+=ry;dw+='<ul>';while(b<titles.length&&b<20&&b<maxresults){if(y!=-1){urls[c]=urls[c]+'?m=0'}if(commentYN=='yes'){comments[c]=' - '+commentsNum[c]}else{comments[c]=''};dw+='<li><a href="'+urls[c]+'" rel="nofollow"><img alt="'+titles[c]+'" src="'+thumb[c]+'"/></a><div class="title"><h3><a href="'+urls[c]+'" rel="nofollow">'+titles[c]+'</a></h3><span>'+time[c].substring(8,10)+'/'+time[c].substring(5,7)+'/'+time[c].substring(0,4)+comments[c]+'</span></div></li>';if(c<titles.length-1){c++}else{c=0}b++}dw+='</ul>'};urls.splice(0,urls.length);titles.splice(0,titles.length);document.getElementById('related-posts').innerHTML=dw};
    //]]>
    </script>
    <b:loop values='data:post.labels' var='label'>
    <script expr:src='&quot;/feeds/posts/default/-/&quot; + data:label.name + &quot;?alt=json-in-script&amp;callback=related_results_labels&quot;' type='text/javascript'/>
    </b:loop>
    <script type='text/javascript'>var maxresults=6;removeRelatedDuplicates();printRelatedLabels('<data:post.url/>');</script>
    </div>
    <div style='clear:both'/>
    </b:if>

maxresults là số bài viết liên quan được hiển thị, mình đặt là 6. Mặc định số lượng comments sẽ được hiển thị, nếu bạn không muốn hãy thay ký tự yes màu tím thành ký tự khác, no chẳng hạn. Số lượng bài viết ở mỗi nhãn được tải về từ feed lấy theo mặc định là 25 bài mới nhất, nếu nhiều hơn mình nghĩ sẽ làm chậm tốc độ blog.

Về CSS cũng như bao thủ thuật khác mình không chú trọng đến giao diện mà quan tâm đến việc hiển thị trên các trình duyệt nhiều hơn. Ngoài ra mặc dù thông tin hiển thị bằng Javascript nhưng mình vẫn thêm thẻ alt cho ảnh, tiêu đề đặt trong cặp thẻ H3 và thuộc tính rel=nofollow cho thẻ liên kết. Mình nhận thấy Google vẫn hiển thị thông tin viết bởi Javascript trong kết quả tìm kiếm.