s3cmdを使う

Amazon S3を使う事になったので、コマンドラインツールのs3cmdをセットアップしてみました。

まずは、Mac。
macportsでインストール出来るので、

$ sudo port install s3cmd

でインストールしました。

続いてWindows、というかCygwin。

  • git
  • python
  • python-setuptool

これらをsetup-x86.exeからインストールします。

次に、pipをインストールします。

$ easy_install pip

続いてpython-dateutilをインストールします。

$ pip install python-dateutil

そして、s3cmdをインストールします。
まずはgitからダウンロード。Macとバージョンを揃えたいのでブランチを指定。

$ git clone -b branch-1.0.x https://github.com/s3tools/s3cmd.git

そしてsetup.pyを実行します。

$ cd s3cmd
$ python setup.py install

以上、Cygwin.

続いてs3cmdのコンフィグを実施します。
ここからはMacもCygwinも共通です。

$ s3cmd --configure

Access Key: # Access Key を入力
Secret Key: # Secret Key を入力

Encryption password: #空のままEnter
Path to GPG program: #空のままEnter

Use HTTPS protocol [No]: #空のままEnter

HTTP Proxy server name: #空のままEnter

Test access with supplied credentials? [Y/n] n # MacもCygwinもテストは403エラーになってしまうのでスキップ

Save settings? [y/N] y

これでs3cmdが使えるようになりました。
試しにファイルをアップロード

$ s3cmd put test.gz s3://example/test.gz

[Adobe Analytics] ADBMobileSample-1.1-Android で java.lang.IllegalArgumentException: provider=network エラー

Adobe Mobile SDKのAndroidサンプルアプリをAndroidエミュレーターで起動しようとすると、java.lang.IllegalArgumentException: provider=network というエラーが出てアプリが起動しませんでした。

どうやらエミュレーターではLocationManager.NETWORK_PROVIDERが使えないのですかね?
対策として、LocationManager.NETWORK_PROVIDERが使えない場合は使わない、という元も子もない対策でしのいでます。

MenuActivity.java の 137行目

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);

これが問題なので、下記のようにif文で囲ったらサンプルアプリが起動しました。

if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
  locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}

参考したサイトは毎度おなじみStack Overflow
Caused by: java.lang.IllegalArgumentException: provider=network

[Adobe Analytics] HTML5動画計測

SiteCatalystの頃から使われている動画計測手法、Milestone型計測を使って、HTML5動画計測を実装したサンプルコードを載せておきます。
Video Tracking Test

ちなみに上記テストページに載せている動画はオープンソースの3DCGソフトウェアBlenderで作成された「Big Buck Bunny」というムービーです。
Big Buck Bunny – Wikipedia, the free encyclopedia

実装したコード:

s.loadModule("Media");
s.Media.trackWhilePlaying = true;
s.Media.segmentByMilestones = true;
s.Media.playerName = "My_HTML5_Player";
s.Media.trackVars="events,eVar11,eVar12";
s.Media.trackEvents="event11,event12,event13";
s.Media.trackMilestones = "25,50,75";
s.Media.trackUsingContextData = true;
s.Media.contextDataMapping = {
	"a.media.name" : "eVar11",
	"a.contentType" : "eVar12",
	"a.media.timePlayed" : "event11",
	"a.media.view" : "event12",
	"a.media.complete" : "event13"
};

function playerHandler(e){
    if (myvideo.currentTime > 0) {
        currentTime = myvideo.currentTime;
    }
    switch(e.type){
        case "play":
            if(!videoOpened){
                s.Media.open(myvideo.src, myvideo.duration, s.Media.playerName);
                s.Media.play(myvideo.src, 0);
            }else{
                s.Media.play(myvideo.src, currentTime);
            }
            videoOpened = true;
	    break;
        case "pause":
            s.Media.stop(myvideo.src, currentTime);
	    break;
        case "ended":
            s.Media.stop(myvideo.src, currentTime);
            s.Media.close(myvideo.src);
	    break;
        default:
	    break;
    }
}

if (document.getElementById("myvideo")) {
	var videoOpened = false;
	var currentTime = 0;
	var myvideo = document.getElementById("myvideo");
	myvideo.addEventListener("loadedmetadata",playerHandler,false);
	myvideo.addEventListener("play",playerHandler,false);
	myvideo.addEventListener("pause",playerHandler,false);
	myvideo.addEventListener("ended",playerHandler,false);
}

新しい計測手法のHeartbeat型計測は別の機会にやってみます。

ドメインを統一

このサイトのURLはwww.kwonline.orgですが、以前はサブドメインなしのkwonline.orgでもアクセス出来ました。

しかし、同じページにURLが二つもあると、Web解析的にもやりづらいのと、検索エンジンに両方のURLがインデックスされてしまいます。
そこで、URLをwww.kwonline.orgで統一する事にしました。

Apacheの.htaccessを使うやり方です。
ルートディレクトリに、下記のような.htaccessファイルを置いてあります。

.htaccess

RewriteEngine On

# Force redirect to www
RewriteCond %{HTTP_HOST} ^kwonline\.org
RewriteRule ^(.*) http://www.kwonline.org/$1 [R=301,L]

この記述により、サブドメなしのkwonline.orgにアクセスしても、強制的にwww.kwonline.orgに301リダイレクトされます。

[Adobe Analytics] Mobile SDK 4.x でアプリ計測する際の小技

久々にスマホアプリをSiteCatalystで計測する方法について調べる機会がありました。

現在リリースされているアプリ計測ライブラリだと、昔のような

s.pageName = "top";
s.prop1 = "main";
s.eVar1 = "man";
s.events = "event1";
s.track();

みたいな実装をしないんですね。

Context Data and Adobe Mobile Analytics: Change is Good

で、代わりにContext Dataに入れた値をProcessing Rule (処理ルール)で変数に入れるという。

HashMap cdata = new HashMap<String, Object>();
cdata.put("my.section", "main");
cdata.put("my.gender", "man");
cdata.put("my.action", "login");
Analytics.trackState("top", cdata);

みたいに実装して、Processing RulesでContext Dataからそれぞれ任意の変数に値をコピーする、と。
この方がより直感的だ、と言われてるそうですが、昔ながらのSiteCatalystのインプリに慣れてるので、かえって心地悪い。
あと、Processing RuleだとビーコンをCharlesやBloodhoundで見て目視、という確認がやりづらい。

従来のs変数に直接値を入れるやり方がもう出来ないのか?という訳でもありませんでした。
Processing Rulesがサポートしていないproducts変数や、events変数のシリアライゼーションは”&&”を付けて直接値を代入するやり方です。

Products Variable – Android SDK 4.x for Marketing Cloud Solutions

cdata.put("&&products", "Category;Product;Quantity;Price");

見慣れたproducts変数の構文です。

Event Serialization – Android SDK 4.x for Marketing Cloud Solutions

cdata.put("&&events", "event1:12341234");

実際に使った事はないんですが、お馴染みのイベントシリアライゼーションの書き方です。

というわけでビーコンパラメータ名(変数名ではない)に、”&&”を付けることで、Context Dataではなく、通常のパラメータとして処理されるようです。
パラメータ名だとこうなります。

  • prop1 → c1
  • eVar1 → v1
HashMap cdata = new HashMap<String, Object>();
cdata.put("&&c1", "main");
cdata.put("&&v1", "man");
cdata.put("&&events", "event1");
Analytics.trackState("top", cdata);

pageNameはtrackStateの第一引数なので仕方ない。
で、ビーコンをログで見るとちゃんとパラメータに入ってますね。
log
&c. から &.c の間に入るとContext Data扱いになり、Context DataはProcessing Rulesで拾わない限りレポートには出てきません。
で、”&&パラメータ名”という書式でセットすれば、&c. ~ &.c の外につくので、Context Dataにならない。
そのため、Processing Rulesを使わなくても、直接値をセット出来る、という仕組みです。

この”&&パラメータ名”の仕組みを使って直接値をセットすれば、”D=”のDynamic Variablesも使えるので

cdata.put("&&c1", "foobar");
cdata.put("&&v1", "D=c1");

という書式でprop1の値をeVar1にコピーする、おなじみのインプリも可能です。

events変数に数値を入れるカウンタ型を使う時も

cdata.put("&&events", "event2=5");

この書き方で対応します。

Javascript で Unicode Escape Sequence 変換

昔PHPで書いたUnicode Escapeツールを載せてましたが、今度はJavaScriptで書いたので載せます。

Unicode Escape Sequence 変換ツール

日本語などのマルチバイト文字を\uXXXX形式にUnicodeエスケープします。

こういう風にエスケープ出来ます。

ほげ → \u307b\u3052

ASCIIコード127番以上の文字だけエスケープするので、空白や改行、半角記号などはエスケープしません。
Unicodeエスケープした文字列をアンエスケープして戻す事も出来ます。

ソースですが、Escapeを行う部分はこうなってます。

var escapeUnicode = function(str) {
    var code = '';
    var head = {1: '\\u000', 2: '\\u00', 3: '\\u0', 4: '\\u'};
    return str.replace(/[^\x00-\x7F]/g, function(c) {
        return head[(code = c.charCodeAt(0).toString(16)).length] + code;
    });
};

エスケープした時に、\uXXXXの4ケタになるように、頭に0を付けて詰めてます。
また、マルチバイト文字だけエスケープして、シングルバイトの記号はエスケープしないように、ASCIIコード127以下の文字は置き替えません。正規表現[^\x00-\x7F] の部分です。
16進数の7Fは、10進数の127なので、つまり0から127に該当しない場合だけ変換します。

つづいてUnesacpeを行う部分はこうです。

var unescapeUnicode = function(str) {
  return str.replace(/\\u([a-fA-F0-9]{4})/g, function(m0, m1) {
    return String.fromCharCode(parseInt(m1, 16));
  });
};

正規表現で\uXXXXを表すと\\u([a-fA-F0-9]{4})なので、このパターンに一致する部分を変換する、という仕組みです。

再開します

昔書いてましたが、またしてもただのメモを書き綴ります。
プログラミング、Linux、Web解析、デジタルマーケティングなどなど。
毎度不定期更新。