← back to Boomer Calculator

components/Ads.tsx

84 lines

'use client'

import { useEffect } from 'react'
import { Capacitor } from '@capacitor/core'

/**
 * Platform-split monetization.
 *
 *  • WEB (boomercalc.com / vercel)  → Google AdSense Auto-ads (legit on the web).
 *  • NATIVE iOS app (Capacitor)     → Google AdMob banner (Apple-compliant; AdSense
 *                                     web tags are NOT permitted inside apps).
 *
 * Capacitor wraps the SAME static `out/` for both, so the decision is made at
 * runtime via Capacitor.isNativePlatform() — never inject AdSense into the app,
 * never initialize AdMob on the web.
 *
 * The AdMob IDs below are the REAL ids for "Boomer Calc" (AdMob console,
 * pub-5278231299883833, created 2026-08-07). The app id also lives in
 * ios/App/App/Info.plist (GADApplicationIdentifier).
 */

const ADSENSE_CLIENT = 'ca-pub-5278231299883833'

// Real AdMob ids for Boomer Calc (iOS).
const ADMOB = {
  iosAppId: 'ca-app-pub-5278231299883833~7368317108',
  iosBanner: 'ca-app-pub-5278231299883833/7591678383',
}

function isNative(): boolean {
  try {
    return Capacitor.isNativePlatform()
  } catch {
    return false
  }
}

export default function Ads() {
  useEffect(() => {
    if (isNative()) {
      // ---- NATIVE: AdMob ----
      // Dynamic import so the web bundle never pulls the native-only plugin.
      ;(async () => {
        try {
          const mod = await import('@capacitor-community/admob')
          const { AdMob, BannerAdPosition, BannerAdSize } = mod
          // App Tracking Transparency is its own call in v7; personalization
          // degrades gracefully if the user denies.
          try {
            await AdMob.requestTrackingAuthorization()
          } catch {
            /* ATT unavailable (<iOS14) or already answered — ignore */
          }
          await AdMob.initialize({
            initializeForTesting: false,
          })
          await AdMob.showBanner({
            adId: ADMOB.iosBanner,
            adSize: BannerAdSize.ADAPTIVE_BANNER,
            position: BannerAdPosition.BOTTOM_CENTER,
            isTesting: false, // real ad unit; AdMob limits serving until the app is approved
          })
        } catch (e) {
          // Never let an ad failure break the (joke) calculator.
          // eslint-disable-next-line no-console
          console.warn('[Ads] AdMob init skipped:', e)
        }
      })()
    } else {
      // ---- WEB: AdSense Auto-ads ----
      if (typeof document === 'undefined') return
      if (document.querySelector('script[data-boomer-adsense]')) return
      const s = document.createElement('script')
      s.async = true
      s.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ADSENSE_CLIENT}`
      s.crossOrigin = 'anonymous'
      s.setAttribute('data-boomer-adsense', '1')
      document.head.appendChild(s)
    }
  }, [])

  return null
}