adstage
Web SDK広告

共通機能

このドキュメントでは、各広告タイプのドキュメントで繰り返し説明されていた「共通の概念」を 1 か所にまとめてメンテナンスしやすくし、広告タイプのドキュメントでは 各タイプ固有の機能 に集中できるようにしています。

🧱 基本構造 & 共通の呼び出しパターン

// 1) SDK の初期化(アプリ全体で 1 回)
AdStage.init({
  apiKey: 'your-api-key',
  debug: process.env.NODE_ENV === 'development'
});
 
// 2) コンテナ DOM の準備後に呼び出し(id と Element のどちらも可)
AdStage.ads.banner('banner-container', { /* オプション */ });
// AdStage.ads.text(element, { /* オプション */ });
// AdStage.ads.video('video-wrapper', { /* オプション */ });
 
// 3) 必要に応じて手動で削除(ほとんどの場合は不要: 自動クリーンアップに対応)
AdStage.ads.destroy(slotId);

React / Next.js Provider の共通パターン

import { AdStageProvider, useAdStageInstance } from '@adstage/web-sdk';
 
// layout / root
<AdStageProvider config={{ apiKey: process.env.NEXT_PUBLIC_ADSTAGE_API_KEY, debug: true }}>
  {children}
</AdStageProvider>
 
// 個別のコンポーネント
function BannerSlot() {
  const adstage = useAdStageInstance();
  const ref = useRef(null);
  useEffect(() => {
    if (!adstage || !ref.current) return;
    const id = adstage.ads.banner(ref.current, { width: '100%', height: 250 });
    return () => adstage.ads.destroy(id);
  }, [adstage]);
  return <div ref={ref} style={{ height: 250 }} />;
}

⚙️ 共通オプション一覧

オプション型説明適用対象
onClickfunction(adData)広告クリック時のコールバック全タイプ
adIdstring特定の広告を強制的に指定全タイプ
language'ko' | 'en' | 'ja' | 'zh'言語フィルター全タイプ
deviceType'MOBILE' | 'DESKTOP'デバイスフィルター全タイプ
country国コード(ISO2)国フィルター全タイプ

広告タイプ別の固有オプションは、各ドキュメント(バナー/テキスト/動画)を参照してください。

🔄 ライフサイクル & 内部動作

graph TD
  A[init の呼び出し] --> B[slot 関数の呼び出し]
  B --> C[コンテナの探索/リトライ]
  C --> D[サーバーへの広告リクエスト]
  D --> E[非同期読み込み]
  E --> F[レンダリング]
  F --> G[インプレッションのトラッキング]
  G --> H[クリック/インタラクションのトラッキング]

主な特性

  • 即時リターン型: slotId はサーバーの応答前に即座に返される ⇒ UI のブロッキングなし
  • 遅延コンテナへの対応: コンテナがまだ DOM に存在しなくても、一定時間リトライし、追加された時点でレンダリング
  • MutationObserver ベースの自動クリーンアップ: DOM から削除されると destroy() を自動実行
  • 複数広告でも安全: 同じコンテナに重複して呼び出した場合は最新の呼び出しのみ有効(実装ポリシー)

🧪 スロット管理 API

// すべてのスロット情報
const all = AdStage.ads.getAllSlots();
 
// 特定のスロットを照会
const slot = AdStage.ads.getSlotById(slotId);
 
// 手動で削除(必要な場合)
AdStage.ads.destroy(slotId);

スロットオブジェクト(実際のフィールド):

interface AdSlot {
  id: string;                 // スロット ID(slotId)
  containerId: string;        // コンテナ DOM の id
  adType: 'BANNER' | 'TEXT' | 'VIDEO' | 'NATIVE' | 'INTERSTITIAL' | 'POPUP';
  width: number | string;     // 数値(px)または文字列('100%' など)
  height: number | string;    // 数値(px)または文字列('auto' など)
  isLoaded: boolean;          // 広告の読み込み完了の有無
  isVisible: boolean;         // 表示状態
  refreshRate: number;        // 自動更新の周期(秒)
  lazyLoad: boolean;          // 遅延読み込みの有無
  targeting: Record<string, any>;
 
  // スロットのメソッド
  load(): Promise<Advertisement | null>;
  render(ad: Advertisement): void;
  refresh(): Promise<void>;
  destroy(): void;
}

🚀 パフォーマンス & 最適化の共通戦略

戦略説明備考
バックグラウンド読み込み非同期読み込みにより初期レンダリングをブロックしないslotId をすぐに使用可能
遅延コンテナへの対応DOM が後から挿入されるケースを自動処理初期化コードの簡素化
自動クリーンアップメモリ/イベントリークを防止SPA の画面遷移時に有用
最小限の DOM 操作コンテナ内部の DOM のみ更新親レイアウトへの影響を最小化
タイプ別のサイズ最適化バナー/動画はサイズを指定、テキストは高さを自動調整CLS の低減

レスポンシブパターンの共通テンプレート

function selectDeviceType() {
  return window.innerWidth <= 768 ? 'MOBILE' : 'DESKTOP';
}
 
const base = { language: 'ko', deviceType: selectDeviceType() };
const id = AdStage.ads.banner('rwd-banner', { width: '100%', height: 250, ...base });
 
window.addEventListener('resize', () => {
  AdStage.ads.destroy(id);
  const next = AdStage.ads.banner('rwd-banner', { width: '100%', height: 250, deviceType: selectDeviceType() });
});

📦 React / Next.js 推奨パターンのまとめ

パターン説明使用タイミング
Provider でのグローバル初期化SDK の設定は 1 回だけApp/RootLayout
フック(useAdStageInstance)安全な SDK アクセスCSR コンポーネント
useEffect での cleanupdestroy を確実に実行スロットのライフタイムを明確化
Skeleton スタイル.adstage-loading 状態をカスタマイズUX の改善

🎨 共通 CSS クラス

.adstage-ad, .adstage-text-ad, .adstage-video-ad { position: relative; overflow: hidden; }
.adstage-loading { opacity: .6; transition: opacity .15s; }
.adstage-loaded { opacity: 1; }
.adstage-error { outline: 1px solid #f87171; }

タイプ別の追加スタイルは、個別のドキュメントを参照してください。

🛠 デバッグ & モニタリング

デバッグモードの有効化

AdStage.init({ apiKey: 'your-api-key', debug: true });

クリックフック(onClick コールバック)

SDK は adstage:ad:loaded / adstage:ad:error のような DOM CustomEvent を発生させません。広告のインタラクションに対するフックが必要な場合は、スロット作成時に onClick コールバックを渡してください。

AdStage.ads.banner('banner-container', {
  width: '100%',
  height: 250,
  onClick: (adData) => {
    console.log('広告がクリックされました:', adData);
    // 追加のトラッキング/ルーティングのロジック
  }
});

読み込み状態の確認

読み込みが完了したかどうかは、スロットの isLoaded フィールドをポーリングして確認できます(デバッグモードを有効にすると、読み込み/失敗がコンソールに出力されます)。

const slotId = AdStage.ads.banner('banner-container', { width: '100%', height: 250 });
 
const timer = setInterval(() => {
  const slot = AdStage.ads.getSlotById(slotId);
  if (slot?.isLoaded) {
    console.log('読み込み完了:', slot);
    clearInterval(timer);
  }
}, 200);

状態診断ユーティリティ

function dumpAdStage() {
  const slots = AdStage.ads.getAllSlots();
  console.table(slots.map(s => ({
    id: s.id,
    containerId: s.containerId,
    adType: s.adType,
    isLoaded: s.isLoaded
  })));
}

🔐 安全性 & ベストプラクティス

テーマ推奨事項
API キー公開されても問題ないが、権限を最小限にしたキーを使用
イベントトラッキングonClick で追加のトラッキングを行う場合は、非同期で送信してからルーティングすることを推奨
エラー対応デバッグモードのコンソールログとスロットの isLoaded 状態で読み込み失敗を診断
リトライポリシーコンテナの遅延挿入ケースは SDK 自体で処理 → setTimeout の追加の乱用は避ける

❓FAQ(共通)

Q. destroy() は必ず呼び出す必要がありますか?
A. ほとんどの場合は不要です。DOM からの削除は自動で検知されます。ただし、同じコンテナをすぐに別の用途で再利用する場合は、手動で destroy() を呼び出すことを推奨します。

Q. 広告が表示されないのに slotId は返されます。
A. 非同期読み込み中であるか、フィルター(adId / language / deviceType / country)で除外された可能性があります。デバッグモードを有効にして、イベントログを確認してください。

Q. SSR(Next.js)ではサーバー側でレンダリングされますか?
A. いいえ。広告のレンダリングはクライアント側でのみ行われます。use client コンポーネントの内部で呼び出してください。

Q. 同じ位置で連続して呼び出すとどうなりますか?
A. 実装ポリシーにより、既存のスロットが削除され、最後の呼び出しに基づいて維持されます。

目次