ソーシャルとWeb、あるいは検索エンジンとの関係について、SEO(検索エンジン最適化)、SMO(ソーシャルメディア最適化)をへて、SGO(ソーシャルグラフ最適化)から先につながる流れが、頭の中が整理できたので、新幹線の移動時間を利用してまとめてみた。
SEO (検索エンジン最適化)
Webは検索エンジンと共に発展してきた。検索で上位に表示されるページが、よいコンテンツと見なされ、検索ロボットが見つけやすいように、ページを最適化するSEO (Search Engine Optimization) が重視された。ブログやCMSによって、構造的なHTMLとWebサイト設計が普及し、インターネットであらゆる情報が見つかるという夢が広がった。
SMO (ソーシャルメディア最適化)
Twitterの140文字制約という発言のしやすさと、新鮮な情報を早く知りたいというニーズが組み合わさり、リアルタイムストリームが普及した。検索エンジンのパーソナライズではなく、情報の流れを可視化する、という発想の転換。
一人のユーザーがリアルタイムで見られる情報量は限られるので、フォローやハッシュタグ(Twitter)、実名の関係性とLike (Facebook)、サークル(Google+)など、新しいフィルタリング手法が開発された。また、情報をシェアしてもらうために、ユーザービリティやレスポンス向上に膨大な開発リソースが投入され、ソーシャルメディア上での関係性の構築 (Social Media Optimization) が重要になった。
SGO (ソーシャルグラフ最適化)
Facebookは、Open Graph Protocolによって、Web上のコンテンツやユーザーの行動を、リアルタイムにAPIから利用できるようにした。その動きをさらに進め、日常生活の様々な行動をデータとして活用できるように、タイムラインとOpen Graph アプリの連携をリリースした。
すでに数多くのWebサイトやスマートフォンアプリに、ソーシャルプラグインという形で、Facebookがユーザーを追跡可能なビーコンが埋め込まれている。Open Graph APIによって、「料理した」「買った」「訪れた」「泊まった」「学んだ」など、より具体的な行動をリアルタイムに把握できるようになる。ユーザーが行動することでデータが集まり、共有されて、自立的にソーシャルグラフが拡大する。
ユーザー体験とデータ解析の結合
ソーシャルグラフの活用で先行するFacebookに、GoogleとAppleも、AndroidやiOSというプラットフォームを駆使して追従するだろう。ユーザーの関心(Interest Graph)と関係性(Social Graph)に基づいて、いつでも、どこでも(Mobile Graph)、リアルタイムにつながることで、素晴らしいユーザー体験が提供される。
ただし、その逆もまたしかり。あなたが彼らを見つけるように、彼らもあなたを見つけることができる。ユーザー体験とデータ解析は、分ちがたく結びつき、利便性とプライバシーの間で、アイデンティティが試されることになる。法律(コード)が日常生活に大きな影響を与えることが再認識され、群衆と政治の綱引きが繰り返される。
emacsのJavaScript用のメジャーモード、js2-modeをオリジナルのjs2-modeからフォークした、インデントや色々と不便な点を修正したバージョンに変更してみた。
オリジナルだと、こんな感じに間延びしたインデントが、
きっちりと詰まってくれます。
Macのターミナルから、
% git clone git://github.com/mooz/js2-mode.git
% cd js2-mode
% emacs --batch -f batch-byte-compile js2-mode.el
コンパイルされた、js2-mode.elc を emacsのsite-lispにコピー。emacs.el に以下を追記。
(autoload 'js2-mode "js2-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.\\(js\\|json\\)$" . js2-mode))
ついでにnode.jsのWAF、Expressで標準採用されているテンプレートエンジン、Jadeのモードも追加してみる。
Githubからクローンして、
% git clone https://github.com/brianc/jade-mode.git
*.elをsite-lispにコピー。以下を.emacs.el に追記。
(require 'sws-mode)
(require 'jade-mode)
(add-to-list 'auto-mode-alist '("\\.jade$" . jade-mode))
jadeファイルを開くとシンタックスハイライトしつつ、タブキーもよしなに動作してくれます。
FacebookのJavaScript SDKでOAuthを使ったアプリを、localhost環境で開発するための設定方法です。FacebookのJavascript SDKを利用すると、ログインしているユーザーやウォールの情報を取得できます。ただし、FB.loginを呼ぶ際に、Facebookがページのドメイン名をチェックするので、localhost/test.html のようなURLだと、「The specified URL is not owned by the application」というエラーが発生する。それを防ぐために、localhost.goodpic.com というようなサブドメインを、ローカルのホストに設定します。
まずは、Facebookでの設定。Facebook developers から、アプリを選択して、[Settings] > [Basic] を選択。 App Domain にサブドメイン無しのドメイン名(example.com)を入力する。ただし、その下の Website : Site URL: にhttpあるいはhttps から始まるサイトのURL(http://www.example.com) も忘れずに入力しておかないと、App Domainが正しく保存されません。
設定を保存したら、ローカル環境のhostsを書き換える。Macの場合はターミナルから、
% sudo emacs /private/etc/hosts
以下を指定。
127.0.0.1 localhost local.goodpic.com
ターミナルから、hostsの情報をフラッシュする。
% sudo dscacheutil -flushcache
例えば、test.htmlなどのHTMLファイルに以下を記入し、
<div id="fb-root"></div>
<script src="./facebook.js"></script>
<div id="fb-page"></div>
facebook.js ファイルでは、Facebook JavaScript ライブラリを非同期に読みこんでログイン処理をする。MAMPなど、ローカルでHTTPサーバを立ち上げて、http://local.goodpic.com/test.html にブラウザからアクセスすると、OAuth 認証が通った authResponse が正しく返ってきます。
window.fbAsyncInit = function() {
FB.init({
appId : 'YOUR_APP_ID',
channelUrl : 'YOUR_CHANNEL_URL',
oauth : true,
status : true, // check login status
cookie : true, // enable cookies
xfbml : true // parse XFBML
});
// Additional initialization code here
// Fetch facebook page infromartion
FB.api('/215071268504237', function(res) {
var widget = ['<h3>Page Information</h3><ul>'];
for (var key in res) {
widget.push('<li>',key,' = ',res[key],'</li>');
}
widget.push('</ul>');
$('#fb-page').append(widget.join(''));
});
FB.login(function(res) {
if (res.authResponse) {
FB.api('/me', function(res) {
console.log('Good to see you, ' + res.name + '.');
});
FB.api('/215071268504237/feed', function(res) {
var widget = ['<h3>Page messages</h3>'];
console.log(res);
for (var i = 0, len = res.data.length; i < len; i++) {
widget.push('<textarea style="width: 500px;" rows="5">', res['data'][i]['message'],'</textarea><br />');
}
widget.push('');
$('#fb-page').append(widget.join(''));
});
} else {
$('#fb-page').append('<p>Login required to browse page messages.</p>');
}
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/ja_JP/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));