Monday, January 15, 2018

Integrate Facebook comment plugin into your website and notify via email

Facebook comments plugin allows Facebooker comment on a content on your website. The comments of customers or users (guests) are very important for almost website owners. To encourage guests leave their comments, beside the content must be attractive, the responds for comments also should be quickly.

In this article, I'll show you how to integrate Facebook comment plugin into your website and receive the notification via email when a comment is dropped on your website. Let go through below steps.

1. Create a Facebook page

If you still don't have a Facebook page, let create one soon. Facebook page is representative for your website or your business on Facebook. Increasing number of Facebookers who likes or follows your Facebook page will increase the chance to broadcast your website / business on Facebook. Facebook page also is used as an official account to response to comments. Especially when you have many administrators or moderators for your Facebook page.
To create a Facebook page, let go to:

2. Create a Facebook app

Facebook app is a gateway to interact with Facebook's assets. If you want to do any things with Facebook, you should have a Facebook app.
If you still don't have a Facebook app, let create one via:

3. Embed Facebook comments plugin into your website

Link your website with your Facebook app & page. To do this, let add meta tags fb:app_idfb:pages into all pages of your website, for example:
<meta property="fb:app_id" content="645919975544702" />
<meta property="fb:pages" content="174460585975791" />
To get your Facebook app id, go to the Dashboard of your app, see the following sample:

To get your Facebook page id, go to Page >> About and find Page ID at the bottom:

Next, let add Facebook's JavaScript SDK and comment box into each page on your website where you want to guests leave comments. To get the code and comment box, you can go to, find Comments Plugin Code Generator section and put your parameters into boxes then click Get Code button. See below picture for example:

You can change the settings of comment box based on your need, for example I want to show 10 newest comments, I do:
<div class="fb-comments" data-href="" data-numposts="10" data-order-by="reverse_time" data-width="100%"></div>
For counting number of comments of an URL, let use fb-comments-count:
<span class="fb-comments-count" data-href=""></span>comments
The above are important settings that I think you should do, for other settings & how to monitor comments, please see more on:

4. Set up your Facebook app

If you need a page profile for your app, let go to your app >> Settings >> Advanced >> App Page and click Create New Page button.

Or you can select an existing page there if the page has same name with the app and categorized as App Page. To change Category or Name of the existing page, click About menu of the page and click Edit link of Category or Name:

The guide on has a section to enable comment mirroring which allows comments from your webpage will also appear as comments on your Facebook Page post and vice-versa. Using comment mirroring, you can receive a notification on Facebook Pages Manager mobile app when you got a comment on your web page. However it will be deprecated soon according to the post So you won't receive the notification on Facebook Pages Manager mobile app more.

Don't worry, I'll show you a way to get this notification via email. For beginning, let setup a webhook when a new comment is posted. See Webhooks section on for how to. More than thousands of words, I post here my pictures:

In the Webhooks section, Facebook also gives a sample mywebhook.php in PHP. Let rename it to commentwebhook.php and modify it in next step to do what we want.

5. Modify commentwebhook.php

The message sent to this webhook file has the format of JSON, however it lacks some important info. So we need to get this info via Facebook API.
To access Facebook API, you need an access_token. You can get it via Facebook Graph API Explorer

You can test APIs in this tool to get experience on data returned. If you want to have a sample code, let scroll down and click Get Code button at the bottom. The sample code is one among of kinds: Android SDK, iOS SDK, JavaScript SDK, PHP SDK, cURL.
Below is the source code of my commentwebhook.php file:

if ($_GET['hub_verify_token'] === 'XXXXXXXXX-123456789-ABCdef') {
  echo $_GET['hub_challenge'];

$entry = file_get_contents('php://input');
file_put_contents('commentwebhook.log', "\n" . $entry, FILE_APPEND);

//get input message
$input = json_decode($entry, true);
$message = $input['entry'][0]['changes'][0]['value']['message'];
$fb_comment_id = $input['entry'][0]['changes'][0]['value']['id'];
$created_time = $input['entry'][0]['changes'][0]['value']['created_time'];
$from_name = $input['entry'][0]['changes'][0]['value']['from']['name'];
$from_id = $input['entry'][0]['changes'][0]['value']['from']['id'];

//get more details
$url = "$fb_comment_id?access_token=$access_token&fields=permalink_url";//fields=permalink_url,message,from,created_time
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($ch);
$output = json_decode($resp, true);
$permalink_url = $output['permalink_url'];

//send email
$bodyHtml =
"<h1><a href='$from_id'>$from_name</a></h1>
<h3>On: <a href='$permalink_url'>$permalink_url</a></h3>";
$bodyText = "$from_name:\n  $message\n  On: $permalink_url";
$url = '';
try {
 $post = array('from' => '',
 'fromName' => 'Your Website Name',
 'apikey' => '00000000-0000-0000-0000-000000000000',
 'subject' => 'You have a comment',
 'to' => ';',
 'bodyHtml' => $bodyHtml,
 'bodyText' => $bodyText,
 'isTransactional' => true);

 $ch = curl_init();
 curl_setopt_array($ch, array(
  CURLOPT_URL => $url,
  CURLOPT_POST => true,
  CURLOPT_HEADER => false,

 $result=curl_exec ($ch);
 curl_close ($ch);

 file_put_contents('commentwebhook.log', "\n" . $result, FILE_APPEND);
catch(Exception $ex){
 file_put_contents('commentwebhook.log', "\n" . $ex->getMessage(), FILE_APPEND);

You can also get the source code from my GitHub:

In the code, I use ElasticEmail for sending notification email without worrying about email server and inbox. If you like, you can register here for an ElasticEmail free account (can send up to 5000 emails free per day).

OK, now you have a power tool for notifying you immediately when getting a comment on your webpage. Happy?
That's all for today. Any comment is welcome!

Friday, December 22, 2017

C# SEO Tools for Google PageSpeed

PageSpeed is very important for ranking of your website on Google as also as it will get better experience for your customers when surfing your website. So Google provides its PageSpeed Insights tool which will give advices for optimizing your website. When you optimize your website meeting Google's requirements, you website will have higher score and may be your ranking will be higher. The acceptable score should be from 80 points (80 / 100).

There are many things which you need to do for meeting Google's requirements. However 2 things which impacts to your score most are image optimization and minifying JavaScript + CSS.

In this article, I'll introduce my SEO Tools (written by C#) for solving above matters. You can checkout the source code here:

The tool uses the following tools:
Below is the guideline for using this SEO Tools.

1. File XML configuration
Below is an example:
BackupSuffix is for copying the original .CSS or . JS file. For example: E:\test\big.js after optimizing ==> E:\test\big_Copy.js (containing original source code) and E:\test\big.js (minified code).
BackupOverwrite = 0 means every time running this tool, it will check and create a backup file with different suffix starting from _Copy1 to _Copy999; = 1 means all times running this tool, it only creates a backup file with suffix _Copy and overwrites it if existing.
DefaultOutPath is for out put folder (containing optimized images) in terms of you don't specify output folder in command.

2. Optimize only files listed in input file
You can use the following command:
SEOTools.exe -i input_file
For example: input_file is E:\test\files.txt. Output to a folder (e.g. E:\test\output), let use:
SEOTools.exe -i input_file -s subfolder -o output_folder
Subfolder is the folder containing image files for compressing, it is used for creating subfolders in backup folder.

3. Optimize all files in input folder (recursively)
You can use the command:
SEOTools.exe -i input_folder -t I -m FO
By default the tool will use Caesium, you can change to use ImageMagick by option -t I. As my experience Caesium gives smaller file size vs. ImageMagick, however ImageMagick runs faster than Caesium. Both also meets Google PageSpeed Insights.
With this tool, you can run after uploading images to your website or modifying CSS file / JavaScript file. Any comment is welcome.
Merry Christmas and Happy New Year!

Wednesday, December 6, 2017

Quick Start ElasticSearch on Windows

What is ElasticSearch?
ElasticSearch is a distributed, RESTful search and analytics engine capable of solving a growing number of use cases. It is built on top of Apache Lucene. It is commonly used for log analytics, full-text search, and operational intelligence use cases. As the heart of the Elastic Stack, it centrally stores your data so you can discover the expected and uncover the unexpected.

What will you get from this article?
In this article, I'll guide you how to install it on Windows, publish it with your domain, secure it. I also introduce to you first steps to combined it with Kibana and Logstash, so you can create a ELK system which can analyze a huge log data near real time.

Let's go!

Install Java Runtime
ElasticSearch requires Java runtime to run. To check if having Java on your Windows, let open cmd and key:
java -version
If you have no Java or the version < 8.x, let go to Oracle Java website for downloading and installing the latest version or from 8.x.

After installing, let create / update JAVA_HOME system environment variable, set it to the new folder installed Java runtime. For example:

Install & Configure ElasticSearch
Go to and download the zip file. Unpack into a folder, e.g. C:\ES

By default ElasticSearch is configured with a 1 GB heap. For real enviroment, this number is not enough. To set new heap size, you must create a system environment variable ES_HEAP_SIZE and set its value, e.g. 4g. This value depends on the memory size (RAM) of your server, it should be less than half of RAM (reference).

After setting new heap size, open C:\ES\config\elasticsearch.yml, set values for important parameters as the following:
# Path to directory where to store the data (separate multiple locations by comma). F:\data
# Path to log files.
path.logs: F:\logs
# Lock the memory on startup.
bootstrap.memory_lock: true
# Upper limit on the fielddata. Old data will be evicted to make space for the new values if it is over the limit size. Can be set to a percentage of the heap size, or a concrete value like 5gb.
indices.fielddata.cache.size: 40%
# Set the bind address to a specific IP (IPv4 or IPv6).
network.bind_host: ["", "localhost"]
# For ReadonlyREST

rest.action.multi.allow_explicit_index: false
Change the values of parameters upon your server. In which, parameter rest.action.multi.allow_explicit_index is reserved for ReadonlyREST tool which will be used for securing queries.

Start ElasticSearch by running bin\elasticsearch.bat file (e.g. C:\ES\bin\elasticsearch.bat). To set up ElasticSearch as a Windows service, run bin\elasticsearch-service.bat install then go to Windows services manager , find ElasticSearch service and change its Startup Type to Automatic.

After starting, let open a browser and check URL http://localhost:9200/ to see if it is working.

Install Logstash
Go to and download the zip file. Unpack into a folder, e.g. C:\LS

Create a simple config file (e.g. logstash-simple.conf) in bin folder (e.g. C:\LS\bin) with a content as the following example to run Logstash.
input { stdin { } }
output {
  elasticsearch { hosts => ["localhost:9200"] }
  stdout { codec => rubydebug }
Then open cmd, go to bin folder & key below command for starting Logstash:
logstash.bat -f logstash-simple.conf
To make a Windows service for Logstash, you can use Non-Sucking Service Manager (NSSM) tool. Download latest NSSM from its download page, unzip it into a folder, e.g. F:\soft\nssm. Use cmd go to F:\soft\nssm\win64 and run the command:
nssm.exe install Logstash
Then you may fill in values as below and click Install service button:

After that, you can open Windows services manager to start Logstash service.

Install Kibana
Go to Kibana download page, download and unzip Kibana into a folder, e.g. C:\KB
Open config/kibana.yml file and configure some important parameters like:
# The URL of the Elasticsearch instance to use for all your queries.
elasticsearch.url: "http://localhost:9200"
# Time in milliseconds to wait for responses from the back end or Elasticsearch. This value
# must be a positive integer.
elasticsearch.requestTimeout: 30000

Run bin\kibana.bat in the installation folder (e.g. C:\KB\bin\kibana.bat) to start Kibana. Check http://localhost:5601 to see if Kibana works.

You can use NSSM to create a Windows service for Kibana. The above picture means no data has been shipped to Kibana yet. For shipping sample data into Kibana, you can try Winlogbeat which sends Windows event logs such as application events, security events, system events, etc. to Logstash.

Setup nginx to access ElasticSearch via a domain
With above configuration, you can only access ElasticSearch via localhost or IP To access ElasticSearch via a domain, we can use nginx forward request to localhost (you can read my article on this link for how to installing nginx). Of course you can configure ElasticSearch directly on file C:\ES\config\elasticsearch.yml to allow to access it via a domain / public IP without using nginx, but I want to use nginx for allowing read only request to my ElasticSearch, for writing request I will setup for IP This security will be done on ReadonlyREST tool in next step.

Below the configuration for nginx:
server {
        listen      *:80;
        location / {
            root your_web_site_root_folder;
            index  index.html index.htm;
        location /es {
            proxy_pass http://localhost:9200;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
            rewrite ^/es/(.*) /$1 break;
Now you can access ElasticSearch via

Setup ReadonlyREST tool
Go to, select your ElasticSearch version and download.
Open cmdcd to the ElasticSearch home and run the command:
bin/elasticsearch-plugin install file:///download-folder/readonlyrest-<version>.zip
For example, download-folder is C:\ES. After that, let create readonlyrest.yml file in the config folder of ElasticSearch (e.g. C:\ES\config/readonlyrest.yml). Then add rules in this file. For example, I want to allow anything from and other hosts can read only, I can add the following rules:

    - name: "Rule 1 - Allowing anything from localhost"
      hosts: []

    - name: "Rule 2 - Other hosts can only read certain indices"
      actions: ["indices:data/read/*"]
      indices: ["logstash-*"] # aliases are taken in account!

For more examples, you can read here to add configuration snippets into this file.

Finally, your ELK is ready for using in real life. Let enjoy it :)
Any comment is welcome!
See you next time.

Saturday, October 28, 2017

Setup chat bot (wrriten by MS Bot Builder NodeJS) with Nginx + HTTPS on Windows Server

Continuing with my series of articles on chat bot:
In this article, I will cover a solution to set up an production environment for your chat bot written by MS Bot Builder NodeJS with Nginx & HTTPS on Windows Server. In which, you can register your chat bot hosted on any server (not on Azure) with MS Bot Framework.

1. Install Nginx

Download the latest version for Windows from:
Unpack it on a folder (e.g. C:\nginx ) and click nginx.exe to run nginx. Open your browser, run http://localhost/. If you see a screen like below, it means Nginx is running well.

2. Run your chat bot

Assuming that you've coded a wonderful chat bot, let run it.  For example, I have a super chat bot by echoing what user says, it is in app.js file as the following:
var restify = require('restify');
var builder = require('botbuilder');

// Create chat bot
var connector = new builder.ChatConnector({
    appId: 'app id of your bot on MS Bot Framework',
    appPassword: 'password of your bot on MS Bot Framework'

// Receive messages from the user and respond
var bot = new builder.UniversalBot(connector, function(session) {
    session.send("You said: %s", session.message.text);

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 5678, function() {
    console.log('%s listening to %s',, server.url);

// Listen for messages from users'/api/messages', connector.listen());

Run app.js:
node app.js
Note that appId and appPassword will be replaced by your real values when you register your bot on MS Bot Framework.

3. Set up Nginx as proxy for your chat bot

Assuming that you want to run your chat bot on the link: Open nginx.conf file (e.g. C:\nginx\conf\nginx.conf) and add a server configuration for your domain:
server {
        listen      *:80;
        location / {
            root your_web_site_root_folder;
            index  index.html index.htm;
        location /bot {
            proxy_pass http://localhost:5678/api/messages;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
Now you can open the chat emulator for testing with the link to see if it works (see section 3 of Create a Luis Chat Bot on Azure Bot Service - Part 1 for setting the emulator with ngrok):

4. Set up HTTPS

MS Bot Framework just allows to register a bot with HTTPS end point message. So that's why we need to set up HTTPS. Luckily, we can setup HTTPS with free SSL Certificate from Let's Encrypt. You can read my article WAMP 64 Bits + Free SSL (section 5) for how to create a free SSL certificate.

Below is the configuration on nginx for a server with SSL:
server {
        listen       443 ssl;
        ssl_certificate      C:/ProgramData/letsencrypt-win-simple/;
        ssl_certificate_key  C:/ProgramData/letsencrypt-win-simple/;
        ssl_trusted_certificate C:/ProgramData/letsencrypt-win-simple/<hex number>-crt.pem;
        ssl_session_cache    shared:SSL:50m;
        ssl_session_timeout  1d;
        ssl_ciphers EECDH+AESGCM:EECDH+AES;
        ssl_prefer_server_ciphers  on;
        location / {
            root your_web_site_root_folder;
            index  index.html index.htm;
        location /bot {
            proxy_pass http://localhost:5678/api/messages;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
Test again on the emulator with

5. Register your bot

Go to, sign in and click My bots menu for registering your bot. Remember to select Register an existing bot built using Bot Builder SDK when creating new bot.
It will open a page for you keying your bot info. Note that Messaging endpoint is
Click Create Microsoft App ID and password to create app id & password for your bot. Paste your app ID to the required box then copy the app id & password into the source code of your bot (e.g. appIdappPassword in section 2). Save the setting.

Now you can click Test button on top right for testing your bot directly from the website For example:

You can also connect your chat bot to other channel like Facebook (see Create a Luis Chat Bot on Azure Bot Service - Part 2 for how to connect with Facebook).

Alright, you have known how to set up a production environment for your chat bot which can be hosted any where.

Have fun! Any comment is welcome.

Sunday, October 15, 2017

MS SQL SMS export large data to Excel without breaking format

If you often work on MS SQL, surely sometimes you want to export large data (result a query) to Excel file. After querying on MS SQL SMS (Microsoft SQL Server Management Studio), you can use right click on the cell top left then select "Copy with Headers" and copy to Excel file or "Save Result As" and save to a CSV file.

However 2 these functions have their problems. "Copy with Headers" cannot copy large data.  "Save Result As" often breaks CSV format if your data contains some special characters.

Fortunately, there is another function for exporting large data without breaking its format. Right click on your database and choose Tasks >> Export Data...

For Data Source, choose SQL Server Native >> select Server name >> select your Database, see the following for example:

Next, select Destination as Microsoft Excel & specify Excel file path.

Next, select Write a query to specify the data to transfer.

In next step, paste your query into or select a file containing your query. In the step Review Data Type Mapping, let review again columns have been converted data (Source Type vs. Destination Type). If you want to fix, click Back to select again Destination Type for converting.

If they are ok, click Next then Finish (don't worry for warning signs). Waiting a moment and you will have your Excel file with correct format you wanted.

Yeah! This is a small tip for you, hope it is useful. Share it to your friend for helping him or her out 😍. Any comment is welcome!

Happy Halloween!
Subscribe to RSS Feed Follow me on Twitter!