# Ads (AdMob)

The ads module wraps **Google AdMob** (`google_mobile_ads`) and supports the four
AdMob formats: **banner, interstitial, rewarded and rewarded-interstitial**.

- **Mobile only.** AdMob has no web SDK, so on web every ad call is a silent
  no-op and `KasyAdBanner` renders nothing. This is handled automatically — it's
  always safe to use ads code in shared widgets.
- **Works out of the box.** Until you set real ids, debug builds show Google's
  official **test ads**. Release builds never show test ads.
- **Premium = ad-free.** Users with an active subscription don't see the
  auto-served formats (banner + interstitial). Rewarded formats stay available
  because the user opts in to watch them.

> ⚠ You can only create real ad unit ids after your app is registered in the
> AdMob console (and usually published). Ship a first version without real ids
> (test ads), then add them.

## Enable / disable

Ads ships in `kasy new` (Quick mode). To add it to an existing project:

```
kasy add ads
```

It prompts for your AdMob **app ids** (optional — blank keeps test ids), wires the
native config, the `google_mobile_ads` dependency and the `withAds` flag.

Set ids later anytime with `kasy configure` (an "Ads (AdMob)" section appears).

## Configuration

There are two kinds of value:

1. **App id** (one per platform) — native, build-time. Lives in
   `android/app/src/main/res/values/strings.xml` (`admob_app_id`) and
   `ios/Runner/Info.plist` (`GADApplicationIdentifier`). Set it with
   `kasy configure` / `kasy add ads`. Required by the SDK — the app crashes on
   launch without a valid app id (the template ships Google's test app id).
2. **Ad unit ids** (one per format, per platform) — client env, read at runtime
   from `.env`:

```
ADMOB_ANDROID_BANNER=
ADMOB_IOS_BANNER=
ADMOB_ANDROID_INTERSTITIAL=
ADMOB_IOS_INTERSTITIAL=
ADMOB_ANDROID_REWARDED=
ADMOB_IOS_REWARDED=
ADMOB_ANDROID_REWARDED_INTERSTITIAL=
ADMOB_IOS_REWARDED_INTERSTITIAL=
```

Leave them blank to use test ads while developing; fill the real ids before a
release build.

## Using ads in your app

Everything goes through `googleAdsProvider`
(`lib/core/ads/ads_provider.dart`). The SDK is initialized for you in `main.dart`.

### Banner

Drop the widget anywhere — it reads its ad unit, hides for premium users, and
renders nothing on web:

```dart
import 'package:kasy_kit/core/ads/widgets/kasy_ad_banner.dart';

const KasyAdBanner();                          // standard banner
const KasyAdBanner(size: KasyAdBannerSize.mediumRectangle);
```

### Interstitial

```dart
final ads = ref.read(googleAdsProvider.notifier);

// Show, respecting a cooldown so you don't spam the user (default 50s):
await ads.showInterstitialIfElapsed();

// Or force one:
await ads.showInterstitial();
```

### Rewarded / Rewarded-interstitial

The user watches an ad and earns a reward. The reward is also verified
server-side (see SSV below) — never grant anything valuable from the client
callback alone.

```dart
await ads.showRewarded(
  onReward: (reward) {
    // Optimistic UI only; the real grant is the server's job (SSV).
    debugPrint('Earned ${reward.amount} ${reward.type}');
  },
);

await ads.showRewardedInterstitial(onReward: (reward) { /* … */ });
```

## Server-Side Verification (SSV) — secure rewards

For rewarded formats, AdMob calls **your backend** to confirm the user really
watched the ad, then your backend grants the reward. This is the only ad piece
that touches the server, and it's what makes rewards tamper-proof.

The app already forwards the signed-in user's id (`setServerSideOptions`), so
your endpoint knows who to credit. You only need to deploy the endpoint and set
its URL in the AdMob console (per rewarded ad unit → SSV callback).

| Backend | Endpoint | Reference |
|---|---|---|
| Firebase | `ads-verifyAdReward` Cloud Function | `functions/src/ads/ads_functions.ts` |
| Supabase | `verify-ad-reward` Edge Function | + `grant_ad_reward()` SQL (migration) |
| API (your server) | you implement `GET /ads/verify-reward` | contract in the API README |

All three verify the ECDSA signature against Google's public keys
(`https://gstatic.com/admob/reward/verifier-keys.json`) and grant the reward
idempotently (keyed on `transaction_id`). The grant itself (coins, lives,
no-ads pass…) is a clearly marked hook you customize.

No secret is required — verification uses Google's public keys.

## Removing ads

`kasy remove ads` (or not selecting it) strips the dependency, the `lib/core/ads`
code, the native config and the `withAds` flag.
