SPAに広告タグなどの外部jsを動的に読み込めるようにするnodeパッケージを作成した話

2 min read読了の目安(約2100字

概要

タイトルにある通り、vue-script-insertという、SPAに広告タグなどの外部jsを動的に読み込めるようにするnodeパッケージを作成
vue、nuxtで利用可能なvueコンポーネントとして作成した。

https://github.com/tf0101/vue-script-insert

開発動機

まず、SPAにはscriptタグを動的に埋め込むと動作しないという問題がある。
この原因だが、SPAでは動的に埋め込んだ外部jsのdocument.writeが無視されるという仕様があるからだ(HTML解析が始まってからDOM操作によって追加された外部スクリプトのdocument.writeは無視される)
これの何が問題かというと、広告タグなどはscriptタグを埋め込む方式のものが多く、document.writeが使用されていると広告が表示されなくなってしまう
既にGoogleAdsens用のパッケージは存在するものの、他ASPサービス用のパッケージが存在せず自分で実装するしかなかったのでパッケージ化した

問題解決へのアプローチ

問題点

SPAの、動的に埋め込んだ外部jsのdocument.writeが無視されるという仕様が問題(HTML解析が始まってからDOM操作によって追加された外部スクリプトのdocument.writeは無視される)

解決手法の提案

  • 提案1 そもそも外部スクリプトにdocument.writeを使わないようにする
    外部スクリプトが自分の管理下にある場合はこれでいいが(document.writeを使わないようにすればいい)、第三者の管理下にあるのが一般的(広告タグなど)であり自身で制御できないので却下

  • 提案2 HTML解析前にDOM操作によって外部スクリプトを追加する
    HTML解析前に外部スクリプトを追加してしまえばいい、iframeなどで別途HTMLを作成してその中で外部スクリプトを追加すれば、まだ本体のHTML解析は始まっていないのでdocument.writeのあるライブラリも読み込める

提案2の手法を実装する

解決策

  • HTML解析前にDOM操作によって外部スクリプトを追加する
    iframeを使うことで擬似的に別のHTMLをつくり、そこでライブラリを読み込めばiframeは今この場で生成しているのでHTML解析がまだ始まっておらず、document.writeのあるライブラリも読み込める

利用想定シーン

ネット広告のクリック&PV型広告ではGoogleAdsensと他サービスでは報酬に3倍以上の差があり選択肢としてはGoogleAdsensの一択になる、しかしながらGoogleAdsensは審査が厳しく「審査に通るまでの間」や「審査に通らないジャンルのサイト」などは他ASPに頼るほかない、そのような場合に本パッケージが活かせるのではないか?

使い方

インストール

$ npm install vue-script-insert

コード

//Vue

<template>
    <!--広告ブロックを埋め込みたい箇所-->
    <VueScriptInsert :url="adv_url" :id="adv_id" :layout="adv_layout"></VueScriptInsert>
</template>

<script>
import VueScriptInsert from 'vue-script-insert'

export default {
    components: {
        VueScriptInsert
    },
    data() {
        return {
            adv_url:'tag',
            adv_id:'id',
            adv_layout:{
                width: "1080px",
                height :"110px",
                },
            }
        }
    }
</script>

外部スクリプトを埋め込みたい箇所に <VueScriptInsert></VueScriptInsert>を挿入し引数を渡す。

引数の詳細

<VueScriptInsert></VueScriptInsert>に渡す引数の詳細

  • url(string):埋め込みたい外部スクリプトを含む構文
    <script>~</script>など
  • id(string):id属性値
  • layout(object):cssレイアウト

レイアウトを細かく設定したい場合

cssを細かく設定したい場合は以下のようにして#id iframe{}内で属性値設定も行える

<style>
    #id iframe{
        ・・・
    }
</style>