Open2

Remix+CloudflareでWebサイトを作る 50(scriptタグで広告が表示できない)

saneatsusaneatsu

【2025-02-19】scriptタグで広告が表示できない

背景

以下のような形式でサイトに広告を表示したい。
publicc/hoge.html にこのコードを書いて、 http://localhost:5173/hoge.html にアクセスすると正しく表示される。

<script type="text/javascript">
var hoge = {
  ad_id: "xxxxxx",
};
</script>
<script type="text/javascript" src="https://example.js"></script>

試したこと(解決できず)

https://zenn.dev/goshouhiro/articles/react-ninja-admax
https://qiita.com/tacchan5424/items/4627d21a1bc7d3b17b05

しかしhtmlではなくtsxファイルで表示したい、ということで上記などを参考にしながら以下のようにした。

const cleanup = () => {
  const scripts = document.querySelectorAll('script[data-ad="true"]');
  for (const script of scripts) {
    script.remove();
  }
};

export function Ad() {
  useEffect(() => {    
    cleanup();

    const inlineScript = document.createElement("script");
    inlineScript.innerHTML = `
      var hoge = {        
        ad_id: "xxxxxx",                
      };
    `;
    inlineScript.setAttribute("data-ad", "true");
    document.body.appendChild(inlineScript);
    
    const externalScript = document.createElement("script");
    externalScript.src = "https://example.js";  
    externalScript.setAttribute("data-ad", "true");  
    document.body.appendChild(externalScript);
    
    return cleanup();
  }, [])

  return (
    <div style={{ width: "100%", minHeight: "100px" }} />
  );
}

これではうまくいかなかった。

解決方法

原因

https://qiita.com/kazu_death/items/c3a2397349cf63a8ea68

要は外部JavaScript、今回の場合 https://example.js の影響でうまくいかないっぽい。
そしてこの記事では postscribe というものを使用している。
これはTypeScriptでは利用できないので、 @marshallku/react-postscribe というものを使う。

https://www.npmjs.com/package/@marshallku/react-postscribe

実装

pnpm add @marshallku/react-postscribe
import PostScribe from "@marshallku/react-postscribe";
import { useEffect, useRef } from "react";

const cleanup = () => {
  const scripts = document.querySelectorAll('script[data-ad="true"]');
  for (const script of scripts) {
    script.remove();
  }
};

export function Ad() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current) return;

    cleanup();

    const script = document.createElement("script");
    script.type = "text/javascript";
    script.setAttribute("data-ad", "true");
    script.textContent = `
      window.hoge = {        
        ad_id: "xxxxxx",                
      };
    `;
    document.body.appendChild(script);

    return cleanup();
  }, []);

  return (
    <div ref={ref} style={{ width: "250px", height: "250px" }}>
      <PostScribe html={`<script src="https://example.js"></script>`} />
    </div>
  );
}```

解決までに3日くらいかかってしまった。
AIもフルで使ったけどここまで深いことまではわからず。
JavaScript側が何か特殊なことやってるかも?という頭にはなったけどそこから解決に至るまでが遠かった。

雑に解決方法だけ書いたけど原因もうちょっと深掘って記事にしたい。