Hatena::ブログ(Diary)

IT memorandum

2009年04月16日

OpenXの導入

| 14:53

OpenX AdServerとはPHPで開発されているオープンソース(GPLライセンス)の広告配信システムです。

インストールしたサーバ内で配信するローカル配信、リモートのサーバに配信するリモート配信が可能です。

広告配信における各種設定、充実した統計機能などオープンソースなのが不思議なくらい多機能なシステムです。

※詳しくはOpenXの日本語サイト(公式?非公式??)でどうぞ。



システム要件としましては、Apache、PHP、MySQL or PostgreSQLでWEBを公開している事くらいです。

なお各ミドルウェアのバージョンについては公式サイト(英語)をのマニュアル等を参考にして下さい。

こちらではApache2.2・PHP5.2・MySQL5.0の環境で導入しました。



インストールといってもPHPなのでサーバに設置してパーミッションを適切に設定するだけです。

後は良くできているインストール画面でインストールは完了します。

ここなんかがインストールから設定を含め詳しく解説してくれています。


それでこのOpenXですが、リモートのサーバに広告を貼る時にテキスト広告ですとJavaScriptぐらいしかやり方が無いように思えます。

(XML-RPCはデフォルトでオンになっていないし、オンにしてもXMLRPCのライブラリをインクルードしているのでローカル用に思えます。)


そこで今回はPHPで設置タグを貼れるように機能追加することにしました。


まず下記のPHPスクリプト]を(OpenX設置ディレクトリ)/plugins/invocationTags/oxInvocationTagsにadphp.class.phpというファイル名でアップします。(パーミッションは707)


require_once LIB_PATH . '/Extension/invocationTags/InvocationTags.php';
require_once MAX_PATH . '/lib/max/Plugin/Translation.php';
/**
 *
 * Invocation tag plugin.
 *
 */
class Plugins_InvocationTags_OxInvocationTags_adphp extends Plugins_InvocationTags
{

    /**
     * Return name of plugin
     *
     * @return string
     */
    function getName()
    {
        return $this->translate("PHP Tag");
    }

    /**
     * Return the English name of the plugin. Used when
     * generating translation keys based on the plugin
     * name.
     *
     * @return string An English string describing the class.
     */
    function getNameEN()
    {
        return 'PHP Tag';
    }

    /**
     * Check if plugin is allowed
     *
     * @return boolean  True - allowed, false - not allowed
     */
    function isAllowed($extra)
    {
        $isAllowed = parent::isAllowed($extra);
        return $isAllowed;
    }

    function getOrder()
    {
        parent::getOrder();
        return 9;
    }

    /**
     * Return list of options
     *
     * @return array    Group of options
     */
    function getOptionsList()
    {
        if (is_array($this->defaultOptions)) {
            if (in_array('cacheBuster', $this->defaultOptions)) {
                unset($this->defaultOptions['cacheBuster']);
            }
        }
        $options = array (
            'spacer'      => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'what'          => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            //'clientid'      => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'campaignid'    => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'block'         => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'target'        => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'source'        => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'withtext'      => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'blockcampaign' => MAX_PLUGINS_INVOCATION_TAGS_STANDARD,
            'charset'       => MAX_PLUGINS_INVOCATION_TAGS_STANDARD
        );

        return $options;
    }

    /**
     * Return invocation code for this plugin (codetype)
     *
     * @return string
     */
    function generateInvocationCode()
    {
        $aComments = array(
            'SSL Delivery Comment' => '',
            'Comment'              => $this->translate(''),
            );
        parent::prepareCommonInvocationData($aComments);

        $conf = $GLOBALS['_MAX']['CONF'];
        $mi = &$this->maxInvocation;

        $buffer = $mi->buffer;


       if (isset($mi->withtext) && $mi->withtext != '0') {
            $mi->parameters['withtext'] = "withtext=1";
        }
        if (isset($mi->block) && $mi->block == '1') {
            $mi->parameters['block'] = "block=1";
        }
        if (isset($mi->blockcampaign) && $mi->blockcampaign == '1') {
            $mi->parameters['blockcampaign'] = "blockcampaign=1";
        }
        if (!empty($mi->campaignid)) {
            $mi->parameters['campaignid'] = "campaignid=".$mi->campaignid;
        }
        unset($mi->parameters['cb']);


        $script = MAX_commonConstructPartialDeliveryUrl($conf['file']['js'], true);
        $param = (count($mi->parameters) > 0) ? '&' . implode('&', $mi->parameters) : '';

        $buffer .=<<<BUNNER
<?php
// HTTP出力時の文字コードを設定して下さい
mb_http_output('UTF-8');

\$uri = 'http' . (isset(\$_SERVER['HTTPS']) ? 's' : '') . ':{$script}'
     . '?cb=' . rand(10000000000, 99999999999)
     . '{$param}'
     . '&charset=' . mb_http_output()
     . '&loc=http' . (isset(\$_SERVER['HTTPS']) ? 's' : '') . '://' . \$_SERVER['HTTP_HOST'] . '/' . parse_url(ltrim(\$_SERVER['REQUEST_URI'], '/'), PHP_URL_PASS)
     . (isset(\$_SERVER['REFERER']) ? '&referer=' . \$_SERVER['REFERER'] : '');

\$options = array(
    'http'  =>  array(
        'method'    =>  'GET',
        'header'    =>  'User-Agent: ' . \$_SERVER['HTTP_USER_AGENT'] . "\\r\\n"
                    .   'Cookie: OAID=' . uniqid('') . "\\r\\n"
    )
);

if (\$ad = @file_get_contents(\$uri, null, stream_context_create(\$options))) {
    \$ad = explode('\\n', \$ad);
    if (preg_match('/.*\+\=\s\"(.*)\\.*/', strtr(\$ad[0], array('"+"' => '', '\\\' => '')), \$matches)) {
        \$ad = \$matches[1];
    }
}
print \$ad;
?>
BUNNER;

        return $buffer;
    }

    function setInvocation(&$invocation) {
        $this->maxInvocation = &$invocation;
        $this->maxInvocation->canDetectCharset = true;
    }
}
?>

そして設定ファイル=(OpenX設定ディレクトリ)/var/(ホスト名).conf.phpの366行目あたりにあるoxInvocationTagsセクションの最下行にisAllowedAdphp=1の一行を追加します。


これでゾーン設定の広告表示コード生成時にPHP Tagという選択肢が表示されるようになります。

(※このスクリプトによって損等が生じたとしても一切の責任は負いかねます。)


後、このシステムを使っていると時々広告が配信されない事があります。

それで色々原因を調べてみたら各手法(JavaScript, XML-RPC等)での配信ファイル内の_adSelect関数に問題があるっぽいので以下の様に変更しました。

例えばJavaScriptで配信を行っているとして(OpenX設定ディレクトリ)/www/delivery/ajs.phpの2821行目付近

return;

return $aLinkedAd;


この関数は選択した広告を優先順位に基づくアルゴリズムを用いて配信するかどうかを判定するものだと思うのですが、

問題はこの関数の外側で取得出来なかった時の再取得を実装していないとかじゃないかと思います。


これは仕様かもしれないし、勘違いかもしれないし、別の設定で回避できるのかもしれません。

というかこの変更を行った事により優先順位付けの機能が無効になっているかも・・。


また色々調べて別の解決方法とかあれば書きたいと思います。

てか誰か何か知っていたら教えてください。

トラックバック - http://d.hatena.ne.jp/jun-ya/20090416/1239861185