How to introduce Google DFP（DoubleClick for Publishers）to  Nuxt.js（Vue.js）

SSRモードのNuxt.jsにGoogle DFPを導入しました。
SSRでの事例は多くはないですね。

思ったより苦戦したので、結果を残しておきます。

The article may be in demand overseas, so the following is also in English.

I introduced Google DFP to Nuxt.js in SSR mode.
It seems there are not enough examples for SSR mode.

I struggled more than I thought I would, so I'll leave you with the results.


# 貼るべきタグ / Original tags

以下の二つ。
よくある「`<head>`の中」と「`<body>`の中」というやつです。

The following two.
As usual, one is inside `<head>` and the other is inside `<body>`.

```
<!-- <head>のすぐ下に設置 -->
<!-- placed just below <head> -->

<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script>
  window.googletag = window.googletag || {cmd: []};
  googletag.cmd.push(function() {
    googletag.defineSlot('***', [[***, ***], [***, ***]], 'div-gpt-ad-***').addService(googletag.pubads());
    googletag.pubads().enableSingleRequest();
    googletag.pubads().collapseEmptyDivs();
    googletag.enableServices();
  });
</script>
```

```
<!-- body内に設置 -->
<!-- placed in body -->

<div id='div-gpt-ad-***' style='margin:auto;text-align:center;'>
  <script>
    googletag.cmd.push(function() { googletag.display('div-gpt-ad-***'); });
  </script>
</div>
```

# 苦脳 / How I suffered.

Vue.js向けに結構コード変えないといけないんですとね、、（意外としんどい作業）
初期ロードだとうまく行ったり、でも `vue-router`の遷移後はうまくいかなかったり、などしんどい開発になりますよね。

I had to change a lot for Vue.js (HARD WORK!).

I've experienced some difficulties.
The initial load works, but does not after the `vue-router` transition.


# 結論 / The Answer

`nuxt.config.ts`に記載するのはこれだけ。後の部分はコンポーネントに持たせる。

This is all that needs to be written in `nuxt.config.ts`.

The rest should be given to the component.

```nuxt.config.ts
script: [
      {
        src: 'https://securepubads.g.doubleclick.net/tag/js/gpt.js',
        async: true,
      },
    ],
```

広告用のコンポーネント。 / The component for ads.

/components/atoms/Dfp.vue

```Dfp.vue
<template>
  <div :id="adId" :style="style" />
</template>

<script lang="ts">
import Vue, { PropType } from 'vue'

const style = 'margin: auto; text-align: center;'

interface Data {
  style: string
  adId: string
}

declare const window: any

export default Vue.extend({
  name: 'Dfp',

  data: (): Data => ({
    adId: '',
    style,
  }),

  beforeDestroy() {
    window.googletag.cmd.push(() => {
      window.googletag.destroySlots()
    })
  },

  created() {
     // mountedの前にidをセットする （or 初期値として設定する）
     // Set id before mounted hook, or set it as initial data.
     this.adId = 'div-gpt-ad-***'
  }

  mounted() {
    // window は mounted()以降しか参照できません.
    // あるいはcreated()の中で、if (process.browser) {...} とする
    // window can only be referenced after mounted().
    // Or in created() hook, write it like if (process.browser) {...}

    window.googletag = window.googletag || { cmd: [] }
    window.googletag.cmd.push(() => {
      window.googletag
        .defineSlot(
          '***',
          [
            [***, ***],
            [***, ***],
          ],
          this.adId,
        
        .addService(window.googletag.pubads())
      window.googletag.pubads().enableSingleRequest()
      window.googletag.pubads().collapseEmptyDivs()
      window.googletag.enableServices()
      window.googletag.display(this.adId)
    })
  },
})
</script>

```

あとはこのコンポーネントを広告設置箇所に配置します。

ファイルの中に定数がちりばめられており、保守性には欠けるので、必要に応じて定数ファイルを作成したり `props` を足したり `computed` で切り分けて書いておくと良いですね。

Now, place this component in the location where you want to place the ad.

It's a good idea to create a constant file. Use `props` and `computed` as needed.

# 最後に / Thanks

Qiita向けに、本質的でない部分を隠したり定数を直書きする時、ちょっと寂しくなる。

良き広告ライフを。

Bye👋