archivesの画像をData URIに変換

HTTPリクエストを減らそう運動モジュール

HTTPリクエストを減らすための手段として、ちょっと着目していたのがData URI(データスキーム)という方法。Data URIは、画像や音声などの色々なファイルをbase64エンコードを通して文字列(URI)に変換する技術です。技術のある人が極まると、えらいことできるらしいですが、今回は画像ファイルとHTMLを一体化させるために使います。

ACMS_GET_Plugin_DataUri(仮)

<?php
require_once ACMS_LIB_DIR.'GET.php';

class ACMS_GET_Plugin_DataUri extends ACMS_GET
{
    function get()
    {
        // 変換対象を正規表現パターンで定義
        $regex  = '@<img.*?src="(/'.DIR_OFFSET.ARCHIVES_DIR.'.*?|/'.DIR_OFFSET.THEMES_DIR.'.*?)"@';

        preg_match_all($regex, $this->tpl, $matches);

        if ( empty($matches[1]) ) return $this->tpl;

        foreach ( $matches[1] as $src ) {
            // 拡張子を取得
            $ext    = pathinfo($src, PATHINFO_EXTENSION);
            // ファイル取得後、base64エンコード
            $pair[$src]  = 'data:image/'.$ext.';base64,'.base64_encode(file_get_contents(DOCUMENT_ROOT.$src));
        }

        $pair   = array_unique($pair);
        $raw    = array_keys($pair);
        $data   = array_values($pair);

        //ズバっと置き換え
        $this->tpl  = str_replace($raw, $data, $this->tpl);

        return $this->tpl;
    }
}
?>

このソースコードを、DataUri.phpとして、/php/ACMS/GET/Plugin/内に配置します。アップデートとかには一切対応しないワンタイムモジュールですが、興味のある方はどうぞ。

今回は、%{ARCHIVES_DIR}{path}のような、archivesディレクトリからの参照が確実である画像ファイルパスを対象にして、いい加減に正規表現マッチングをしています。

画像のHTTPリクエストが減る

ウェブページを表示する中で、HTTP通信の時間的コストはかなり高いです。Data URIとして、画像がHTMLの中に文字列として混ざることで、HTTP通信のコストが減少します。細かいファイルをチマチマと個別で読み込むのは想像以上に読み込み時間を食い散らかしています。

a-blog cmsの場合はHTMLと一緒に、キャッシュもバッチリされてしまいますが、そこまで大きな問題にはならないはず。サイトのページ数によってはDBのcacheテーブルの内容積がモリモリ増えてしまいそうですけど。DBの容量に自信がなかったり、サイトのページ数に自信がある場合は要注意です。

肝心の使い方は

以下、plainやvicuna等、index.htmlのテンプレート1枚で完結しているようなテーマを対象にした説明です。

当ハブろぐの場合は、既存のindex.htmlをindex_raw.htmlにリネームし、新しいindex.htmlとして下記のようなテンプレートを作成しました。

<!-- BEGIN_MODULE Plugin_DataUri -->
<!--#include file="index_raw.html" -->
<!-- END_MODULE Plugin_DataUri -->

元のindex_raw.htmlの出力結果を、最後の最後でDataUriモジュールのフィルターにかけているという感じです。対象にできるimgパスがあれば、片っ端からData URIの文字列に置き換えていきます。

変換された画像は下のようなコードに変換されます。下のコードは、サブカラムの鳥さんの写真の場合です。…連続の英数字なのでハミ出ますが気にしない。

<img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA8Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gMTAwCv/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/bAEMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAH4AfgMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAA(以下略!)" width="126" height="126" alt="北端のとり" id="profileImg" />

IEには元のindex_raw.htmlを使います

IEは8以降でないとData URIを表示できません。よって、ルールを使ってUser AgentからInternet Explorerには、すべて元のテンプレートである、index_raw.htmlを直接表示するように設定します。8は対応してますけど、現状のルールにはそんな器用な項目はないので全部ナシです。

そうそう滅多なことは起こらないと思いますが、なんかあったら教えてもらえると助かります。判定をもうちょっと賢くかけばもっと遊べそうですね。ちゃんと速くなるかなー?



携帯電話向けGAモジュール for a-blog cms

Category : a-blog cms

Tags : a-blogcms Google Analytics module

携帯向けGoogle Analyticsとa-blog cms

Google Analytics全般とa-blog cmsの相性の良さは後日言及するとして、今回は携帯対応ということでa-blog cmsのワンソースマルチユースの特徴が特に生きてきます。

同じURLでパソコンにも携帯にもiPhoneにもコンテンツを出力できるので、まとめてアクセス解析したときにも端末ごとの分析が容易になります。たとえば「PCで見られないこのコンテンツはiPhoneで多く見られてる」とか「携帯のときのトラフィックが特定エリアだけ高い」とかですね。

もちろん、絶対数の埋め合わせとかの調整は必要ですし、PCとモバイル用サイトが同じような構成とも限らないので、単純比較というよりも傾向のあぶり出しになりそうですが。サイトによっては興味深いデータが得られるのではないでしょうか。

今回はa-blog cmsでGoogle Analyticsの携帯電話向けトラッキングに対応するための、GETモジュール対応手順をまとめてみます。

GAの携帯電話向けサイト用PHPコードを出すまで



まずはここから。以下に手順を示します。

  1. Google Analyticsのプロファイルを「編集」をクリック
  2. 画面右上の「ステータス確認」をクリック
  3. トラッキングコードの追加手順の「アドバンス」タブを選択
  4. "(1) 何をトラッキングしますか?"の「携帯電話向けのサイト」を選択

以上で、"(2) 携帯電話向けのサイトにコードを貼り付けます" にPHPのコードが表示されます。スクリーンショットで示している所の文字列を控えてください。これが、携帯電話向けのトラッキングアカウントです。コードの他の部分はモジュールのサンプルコードに書いてあるので必要ありません。(今後Google側で変更があれば、サンプルコードも変更する必要がありますが、そのときはそのときで

ga.phpをダウンロード

前項からの続きで、"(3) ファイルをルート ディレクトリにコピーします" から、ga.phpをダウンロードします。これをルートディレクトリに置くわけですが、a-blog cmsの設置先、index.phpと同階層のディレクトリにga.phpをアップロードします

トラッキングアカウントをコードに組み込む

下記のサンプルコードにトラッキングアカウントを埋め込み、/php/ACMS/GET/AnalyticsMobile.phpとしてファイルを作成します。これが後でテンプレートに記述するGETモジュールになります。

<?php
require_once ACMS_LIB_DIR.'GET.php';

class ACMS_GET_AnalyticsMobile extends ACMS_GET
{
    function get()
    {
        $Tpl    = new Template($this->tpl, new ACMS_Corrector());

        // 下記の " MO-0000000-0 " の所を前項で控えた文字列に書き換えます
        $GA_ACCOUNT = 'MO-0000000-0';
        $GA_PIXEL   = 'ga.php';

        $url    = "";
        $url   .= $GA_PIXEL . "?";
        $url   .= "utmac=" . $GA_ACCOUNT;
        $url   .= "&utmn=" . rand(0, 0x7fffffff);

        $refer  = REFERER;
        $query  = $_SERVER["QUERY_STRING"];
        $path   = $_SERVER["REQUEST_URI"];

        if ( empty($refer) )
        {
        $refer  = "-";
        }

        $url   .= "&utmr=" . urlencode($refer);

        if ( !empty($path) )
        {
        $url   .= "&utmp=" . urlencode($path);
        }

        $url   .= "&guid=ON";
        $url    =  str_replace("&", "&amp;", $url);

        $Tpl->add(null, array('tracksrc' => $url));

        return $Tpl->get();
    }
}
?>

テンプレートにモジュールを書く

先ほど作成した AnalyticsMobileモジュールを、携帯向けのテンプレートに記述してください。大まかには下記のサンプルコードをコピー&ペーストするだけで大丈夫なはずです。場所はbody要素の閉じタグの直前です

(前略)
<!-- BEGIN_MODULE AnalyticsMobile -->
<img src="%{HTTP_ROOT}{tracksrc}[raw]" height="1" width="1" />
<!-- END_MODULE AnalyticsMobile -->
</body>
</html>

これでOK

あとは適当な日を置いて、Google Analyticsからレポートを確認しましょう。DoCoMoとかが解析結果にあれば大体成功です。

携帯かどうかというのは、ユーザーのOSの情報として代替的に示されるので、ちゃんと絞り込まないと携帯の情報は取得できません。カスタムレポートやアドバンスセグメントを併用するのが良い感じですが、とっかかりとしては下記の記事のカスタムレポートをそのまま使うのが良さそうです。

携帯用カスタムレポート for Google Analytics | カグア!Google Analytics 活用塾:事例や使い方

a-blog cms v1.3.0では、モバイルトラッキング用のアカウントと、ga.phpのパスを設定項目として、標準実装に滑りこませてしまおうかなーと勝手に検討中です。(他に影響があるような機能でもないので割と気軽)

それまではひとまず、こちらのモジュールを使っていただければと思います!ご質問なりトラブルがあれば、@ahomuまでどうぞ☆



公開と同時につぶやくよ(TwitterAPI叩いてみた)

Category : a-blog cms

Tags : module

POSTモジュールの例

スーパー地味どころか使い所無いですが、エントリーを公開するついでにツイート(笑)するPOSTモジュールを書いてみました。いや、深夜に隣の部屋が盛り上がり始めて睡眠妨害されたもんで、つい。

拡張機能の開発 | a-blog cms - Web制作者のためのCMS のような、開発系の情報もちょろっと出始めているの小出ししてみる次第。

処理の順序

  1. タイトルとリンクを取得して、Tweet文字列を作成
  2. TinyURLにリンクを投げて短縮
  3. TwitterAPIを、PEARのHTTP_Requestで叩く
  4. 本来のエントリー公開処理

PHPを準備する

下のコードを、/php/ACMS/POST/Entry/OpenTweet.phpとして作成します。IDとパスワードは、ぼちぼち書き換えてください。

<?php

require_once ACMS_LIB_DIR.'POST/Entry/Open.php';

class ACMS_POST_Entry_OpenTweet extends ACMS_POST_Entry_Open
{
    function post()
    {
        $twitId = 'あなたのID';
        $twitPw = 'あなたのパスワード';

        $bid    = $_POST['bid'];
        $cid    = $_POST['cid'];
        $eid    = $_POST['eid'];

        /**
         * 遠回しにエントリータイトルを取得します。
         * submitする時点で{entry_title}とかの変数を忍ばせて送った方が良いです。
         * テンプレートの編集を手抜くために今回はこれで。
         */
        $DB     = DB::singleton(dsn());
        $SQL    = SQL::newSelect('entry');
        $SQL->addSelect('entry_title');
        $SQL->addWhereOpr('entry_blog_id', $bid);
        $SQL->addWhereOpr('entry_id', $eid);
        $title  = $DB->query($SQL->get(dsn()), 'one');

        /**
         * リンクを組み立てて更にtinyUrlに投げて短縮します。
         */
        $url    = acmsLink(array('bid'=>$bid, 'cid'=>$cid, 'eid'=>$eid));
        $tiny   = file_get_contents('http://tinyurl.com/api-create.php?url='.$url);

        $tweet  = "NewEntry! $title - $tiny";
        //die($tweet);

        // ここで結果を確認しても良いけど、とりあえず無視。
        $res = $this->entryTweet($twitId, $twitPw, $tweet);

        // 親のpostメソッドを起動して公開処理に戻る。
        return parent::post();
    }

    function entryTweet($id, $pw, $tweet)
    {
        $param = '?status='.rawurlencode($tweet);

        require_once LIB_DIR.'PEAR/HTTP/Request.php';
        $REQ = new HTTP_Request('http://twitter.com/statuses/update.xml'.$param);
        $REQ->setMethod(HTTP_REQUEST_METHOD_POST);
        $REQ->setBasicAuth($id, $pw);
        $res = $REQ->sendRequest();

        if ( !PEAR::isError($res) ) {
            return $REQ->getResponseBody();
        } else {
            return false;
        }
    }
}
?>

設置方法

/themes/system/entry/action.htmlを編集します。本来のACMS_POST_Entry_OpenモジュールをOpenTweetにしちゃってください。

<!-- ▼これを  -->
<input type="submit" name="ACMS_POST_Entry_Open" value="公開" />

<!-- ▼こんな感じに -->
<input type="submit" name="ACMS_POST_Entry_OpenTweet" value="公開してつぶやく" />

使用方法

いきなりエントリーを公開しちゃうと、このモジュールの出番がありません。既に作成してある非公開エントリーを、先ほど用意した"公開してつぶやく"ボタンで公開してください