「現場でプロが培った Google Analyticsの使い方」を読んだ

Google Analyticsを使ったアクセス解析 == 因数分解

Google Analyticsって面白いね。単にアクセスログを見て視覚化して増えた減ったを単純に喜ぶくらいなんかなぁと思っていたけど、実際に本書を読んだら、推論して仮説を立てて検証していくプロセスを実行出来るところが気に入った。

Hello? / Jostein Gaarderに超気に入っている一文があって、それは

'An answer is always the stretch of road that's behind you. Only a question can point the way forward.'

仮説の設定力が重要なのね。というわけで、本書にはそのためのヒントが幾つか散らばっていた。でも、僕はそういうことを検討するためのサイトを持っていないので欲しい、というかなんかつくろう。

ProductName 現場でプロが培った Google Analyticsの使い方 (WEB PROFESSIONAL)
中野 克平
アスキー・メディアワークス / 2079円 ( 2010-02-12 )


  • コンバージョン率の測定はPDCAのC
  • ソーシャルトラフィック
  • 時間帯別の指標からユーザー属性を読み取る
  • 成否の指標を明確にしよう
  • 検索エンジン(yahoo,google)
  • 一本化されたからこれは今後あまり問題にならない?
  • Webプレゼンスをキーワードから判断していく
  • ユーザーの目的はコンテンツを実際に目にすることで変わる
  • アドバンスセグメントで指標を深く読み取る
  • トラフィックの割合の変化はあまり意味が無い

あと、これってSpotfire向きの仕事だよね。だれかそういう使い方してるヒトいるのかなぁ。今度聞いてみよう

googlemapに円を描き入れる

入れてみた。ついでに常に地図の中心から5kmの範囲を示すようにした(twitterで地図の中心から5kmの範囲のtweetをサーチしているので)

最近毎朝アクセスして、昨晩雪が降って道路が凍結してないか確認している。富士と御殿場は天気がかなり違うのでこっちが晴れててもあっちは雪降ってるとかよくある。

Google Maps APIがなかなか楽しい。

ProductName Google Maps APIプログラミング入門
勝又 雅史
アスキー・メディアワークス / 3570円 ( 2010-03-30 )


Flaskをthreadで動かす

MLより

multiprocessingを使えばいいらしい。

import time
from multiprocessing import Process
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
        return "Hi there!!!"

def run():
    app.run()

if __name__ == '__main__':

    app.debug = True

    print "starting process"
    server = Process(target=run)
    server.start()

    print "sleeping"
    time.sleep(5)

    print "ending process"
    server.terminate()
    server.join()

    print "bye..."

どういうシチュエーションでこういう必要性が出るのかいまいちわからんが覚えておこう。

山岡家

凧揚げの帰りに寄ってみた。

こってり家系?普通、中盛、大盛りってあって中盛頼んでみたけど、かなりの量だった。

つけ麺(醤油)は酸味が効いてるスープで美味しいが、色の割にトンコツ薄め?でアブラ多めな感じ。僕はつけ麺頼んだんだけど、普通にラーメンでも良かったかな。

1294657359 1294657364

U隊長の味噌。それから、チャーシュー丼。味噌はちょっと濃いな。次に頼むんだったら、「塩、固め、油少なめ、味薄め」かなぁ。

1294657345 1294657352

店内は席ごとに壁で仕切られていて、ファミリーにもやさしい(子供に飴くれるし)。というかファミリー多かったのでびっくりした。

NU:TONEの新譜

楽しみすぎる

NU:TONE

ProductName Brave Nu World
Nu Tone
Hospital / ?円 ( 2005-03-07 )


ProductName Back of Beyond
Nu Tone
Hospital / ?円 ( 2007-06-18 )


富士川緑地公園で凧揚げしてきた

緑地公園は初めて行った。スケボーのイベントとかやっていて、前から気になっていたんだけど、なかなか行かなかった。

広い!息子も大喜び。

1294656259 1294656265

娘は凧揚げが出来て大満足。

1294656253 1294656271

凧の絵柄は娘が選んだんだけど、僕も気に入っている。あと、今の凧ってめちゃくちゃ軽いのね。

Flaskをgaeで動かす

さっきのやつをgaeで動かしてみる。

git clone https://github.com/gigq/flasktodo.git gmaptweetgae
cd gmaptweetgae

でapplication.pyをFlask用のコードに置き換えてapp.yamlを適当に設定したら

appcfg.py update .

で、できたサイト。多分自分はよく使うので満足。

参考

ProductName Google App Engineプログラミング入門
中居 良介
アスキー・メディアワークス / 1890円 ( 2009-12-23 )


dev_appserver.py

path切ったはずなのに見つからなくて、???

cd /Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/
unzip google_appengine.zip

ってやった。

やった後に「この前も同じことやったよなぁ」と思った。なんか間違ってるのかなぁ?

今日の畑(110109)

キャベツとか白菜のような葉物を植えてないので、なにもないというかまったくもって貧相な畑だ。というかジャガイモ植える予定にしているから、空けとかなきゃいけないんだよね。あと、午前中は日陰になっていて寒いな、この場所。

1294634544

春菊の収穫は2月の終りくらいかなぁ。

1294634529

そら豆は元気だが、スナップエンドウはダメそうだなぁ。

1294634535

今月号のやさい畑はコンパニオンプランツの 特集で、ミョウガにローズマリーがいいらしいので、今季は合間に植えてみることにした。

あと、ジャガイモは変わった品種を植えてみたいなぁ。種とかどこで手に入れるのがいいんだろうかねぇ。となりの畑のおじさんには、旧国道沿いの富士郵便局隣の苗やさんを薦められたんだけど、日曜休みなんだよねぇ。

ProductName やさい畑 2011年 02月号 [雑誌]

家の光協会 / 880円 ( 2010-12-29 )


FlaskとXDMつかってgooglemapとtwitterを連動させるサンプル

HTML5 APIガイドブック コミュニケーション系API編が面白い。ひと通り読んだので、コード書いてみてる。

2章のサンプルコードをFlaskで。サンプルコードは3つのHTMLファイルが必要だけどFlask使えば一つのファイルに全部押し込めるので管理が楽。

gmap2twitter

初期値は富士市役所のあたりから半径5キロ以内のtweetを探すようにした。で地図をドラッグすると、それに伴いtweetも連動して表示されるので、ほーこんなユーザーいるのか!と新たな発見もあった。

この本は入門書として最適かもしれん。

ProductName 徹底解説 HTML5 APIガイドブック コミュニケーション系API編
小松 健作
秀和システム / 2730円 ( 2010-12 )


Flaskコード

#!/usr/bin/env python
# -*- encoding:utf-8 -*-

from flask import Flask

app = Flask(__name__)

@app.route("/")
def processing():
    response = """
<!doctype html>
<html lnag=ja>
<head>
<meta charset="utf-8">
<style type="text/css">
.page { margin: 0px auto; border: 0px; padding: 0px; text-align: center;}
</style>
</head>
<body>
<div class=page>
<h1>gmap2tweet</h1>
<iframe src="/googlemap" id=gmap width="500px" height="500px"></iframe>
<iframe src="/twitter" id=twitter width="500px" height="500px"></iframe>
<div id=mesg></div>
</div>
<script>
  var initialize = function(){
    var origin = location.protocol + "//" + location.host;
    var iframes = document.querySelectorAll('iframe');

    for(var i = 0; i < iframes.length; i++){
      iframes[i].contentWindow.postMessage('init', origin);
    }

    window.addEventListener('message', function(e){
        if (e.origin == origin) {
          document.getElementById('mesg').innerHTML = "receive data via xdm::" + e.data;
          document.getElementById('twitter').contentWindow.postMessage(e.data, origin);
        }
    }, false);
  }
  window.onload = function(){ initialize(); }
</script>
</body>
</html>
"""
    return response

@app.route("/twitter")
def twitter_processing():
    response = """
<!doctype html>
<html lang=ja>
<head>
<meta charset="utf-8">
</head>
<body>
<div id=mesg></div>
<div id=results></div>
<script>
var origin = location.protocol+"//"+location.host;
var parentWin = null;
var api="http://search.twitter.com/search.json?callback=show&rpp=50&geocode=";
var jsonpObj =null;

var sendJsonp = function(latlng, radius){
  if(jsonpObj)
    document.body.removeChild(jsonpObj);
  var scr = document.createElement('script');
  scr.src = api+encodeURIComponent(latlng+","+radius+"km");
  scr.type = "text/javascript";
  jsonpObj = document.body.appendChild(scr);
};

var show = function(obj){
  var results = obj.results;
  var out = '';
  var template = '<img src="#{img}"> <a href="http://twitter.com/\
#{from_user}" target="_blank"><b>#{from_user}</b></a> #{text}<br />\
#{created_at}<hr />';

  for(var i = 0; i < results.length; i++){
    var res = results[i];
    var tmp = template.replace("#{img}", res.profile_image_url) \
.replace("#{from_user}", res.from_user) \
.replace("#{from_user}", res.from_user);
    tmp = tmp.replace("#{text}", res.text) \
.replace("#{created_at}", res.created_at);
    out += tmp;
  }

  document.getElementById('results').innerHTML = out;
};

window.addEventListener('message', function(e){
  if(e.origin == origin) {
    if (e.data == 'init') {
      parentWin = e.source;
    } else {
      document.getElementById('mesg').innerHTML = e.data;
      document.getElementById('results').innerHTML = "読み込み中";
      sendJsonp(e.data, 5);
    }
  }
}, false);
</script>
</body>
</html>
"""
    return response

@app.route("/googlemap")
def google_processing():
    response = """
<!doctype html>
<html lang=ja>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body style="padding:0;margin:0;height:500px">
<div id=map_canvas style="width: 100%; height: 100%; border: 0px"></div>

<script>
var parentWin = null;
var origin = location.protocol + "//" + location.host;

var start = function() {
  var latlng = new google.maps.LatLng(35.164190, 138.678609);
  var myOptions = {zoom: 13, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP};

  var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

  var getCenter = function(){
    var center = map.getCenter();
    var lat = center.lat(); 
    var lng = center.lng();
    if(parentWin) {
      parentWin.postMessage(lat+","+lng, origin);
    }
  };

  window.addEventListener('message', function(e){
    if(e.origin == origin) {
      if(e.data == 'init') {
        parentWin = e.source;
        getCenter();
      }
    } else {
      alert("illegal message from " + e.origin);
    }
  }, false);

  google.maps.event.addListener(map, 'dragend', function(e){getCenter();});
  google.maps.event.addListener(map, 'zoom_changed', function(e){getCenter();});

};

window.onload = function(){start();};
</script>
</body>
</html>
"""
    return response

if __name__ == "__main__":
    app.run()