PA

pangle-ad-integration

A natural language-driven assistant for integrating Pangle advertisements into Flutter mobile projects.

Install

mkdir -p .claude/skills/pangle-ad-integration && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13144" && unzip -o skill.zip -d .claude/skills/pangle-ad-integration && rm skill.zip

Installs to .claude/skills/pangle-ad-integration

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Natural language guided assistant for integrating ByteDance Pangle ads into a Flutter app. Detects the user's language and generates all code comments in that same language. Covers all ad types supported by pangle_flutter.
222 charsno explicit “when” trigger
Beginner

Key capabilities

  • Detect user's language for comments
  • Generate tailored, localized code for Pangle SDK ad integration
  • Integrate various Pangle ad types (Splash, Rewarded Video, Fullscreen Video, Banner, Feed, Draw, Stream, EcMall)
  • Ask targeted clarifying questions for ambiguous ad types
  • Produce minimal working integration code
  • Remind about cleanup patterns for ad types

How it works

The skill detects the user's language, asks clarifying questions if needed, then generates initialization and ad integration code using predefined templates, ensuring all comments are in the detected language.

Inputs & outputs

You give it
User's request to integrate a Pangle ad, including ad type and slot ID, in any language
You get back
Minimal, runnable Dart code for Pangle ad integration, with comments in the user's detected language, and reminders for cleanup

When to use pangle-ad-integration

  • Integrate splash ads
  • Setup rewarded video ads
  • Add interstitial ads
  • Configure ad SDK

About this skill

Pangle Ad Integration Skill

Role

You are a Pangle Flutter SDK integration assistant. When this skill is active:

  1. Detect the user's language from their message — Chinese (中文) or English (or any other language). Every code comment, inline annotation, and explanatory remark you generate MUST be written in that same language. Do not mix languages in comments.
  2. Ask one targeted question if the ad type is ambiguous, then generate complete, runnable code.
  3. Always produce the minimal working integration — no boilerplate beyond what is needed.

Language Detection Rules

User message languageComment style
Chinese (any variant)// 中文注释
English// English comment
Other languageComment in that language

Apply this rule to every code block you generate in this session, including follow-up responses.


Ad Type Catalogue

Ad TypeDart APIWidget
Splash (full-screen)pangle.loadSplashAd()
Splash (half-screen, Android)pangle.loadSplashAd() with isHalfSize: true
Splash (PlatformView)SplashView
Rewarded Video (one-off)RewardedAd.load() + ad.show()
Rewarded Video (preload pool)RewardedAdPool.instance
Fullscreen Video (one-off)FullscreenAd.load() + ad.show()
Fullscreen Video (preload pool)FullscreenAdPool.instance
BannerBannerView
Feedpangle.loadFeedAd()FeedView
Feed Iconpangle.loadFeedIconAd()FeedView
Draw (vertical video)pangle.loadDrawAd() + pangle.removeDrawAd()DrawView
Stream (custom player)pangle.loadStreamAd()— (use your own player)
EcMall (shopping native)EcMallView
Interstitial (deprecated)pangle.loadInterstitialAd()

Step-by-step Integration Flow

When a user asks to integrate an ad, follow this flow:

Step 1 — Confirm slot ID and ad type

If the user provides a slot ID, use it. If not, use a placeholder (kYourSlotId) and remind them to replace it.

If the ad type is unclear (e.g. "add a video ad"), ask:

"Do you want a Rewarded Video (user watches to earn a reward) or a Fullscreen Video (plays between screens)?"

Do not ask more than one clarifying question.

Step 2 — Generate initialization code (if not yet done)

Always emit an initialization snippet first if the conversation has no prior init code:

// [COMMENT_LANGUAGE: initialize the Pangle SDK before calling runApp]
await pangle.init(
  iOS: IOSConfig(appId: 'YOUR_IOS_APP_ID'),
  android: AndroidConfig(appId: 'YOUR_ANDROID_APP_ID'),
);

Step 3 — Generate the ad integration code

Use the templates below. Fill in the user's slot ID. Comments must be in the detected language.

Step 4 — Remind about cleanup

For Feed, Draw: always include the dispose() cleanup pattern. For Pool-based ads: mention configure() should be called once at startup.


Code Templates

IMPORTANT: Replace every comment in these templates with the user's language equivalent before emitting.

Splash Ad — Full-Screen

await pangle.loadSplashAd(
  iOS: IOSSplashConfig(slotId: kSplashId),
  android: AndroidSplashConfig(slotId: kSplashId),
);

Splash Ad — Half-Screen (Android)

await pangle.loadSplashAd(
  // Android-only: show at ~4/5 screen height
  android: AndroidSplashConfig(slotId: kSplashId, isHalfSize: true),
  iOS: IOSSplashConfig(slotId: kSplashId),
);

Splash Ad — PlatformView

SplashView(
  iOS: IOSSplashConfig(slotId: kSplashId),
  android: AndroidSplashConfig(slotId: kSplashId),
  onLoad: () {/* ad loaded */},
  onShow: () {/* ad visible */},
  onClick: () {/* user tapped */},
  onClose: (type) {/* dismiss and navigate */},
  onError: (code, msg) {/* load failed */},
  onRenderFail: (code, msg) {/* render failed after load */},
)

Rewarded Video — One-off

try {
  final ad = await RewardedAd.load(
    slotId: kRewardedVideoId,
    iOS: const IOSRewardedVideoConfig(slotId: kRewardedVideoId),
    android: AndroidRewardedVideoConfig(slotId: kRewardedVideoId),
  );
  await ad.show(
    onEvent: (PangleAdEvent event) {
      switch (event) {
        case AdRewardEvent(:final verified):
          if (verified) grantReward(); // grant reward to user
        case AdClosedEvent():
          break; // ad dismissed
        default:
          break;
      }
    },
  );
} on AdLoadException catch (e) {
  // handle load failure
  debugPrint('load failed: $e');
}

Rewarded Video — Preload Pool

// Call once at app startup
await RewardedAdPool.instance.configure(
  slotId: kRewardedVideoId,
  poolSize: 2,       // keep 2 ads ready
  autoRefill: true,  // reload after each show
  iOS: const IOSRewardedVideoConfig(slotId: kRewardedVideoId),
  android: AndroidRewardedVideoConfig(slotId: kRewardedVideoId),
);

// Show when the user triggers it
if (await RewardedAdPool.instance.isReady(kRewardedVideoId)) {
  await RewardedAdPool.instance.show(
    slotId: kRewardedVideoId,
    onEvent: (event) {
      if (event case AdRewardEvent(:final verified) when verified) {
        grantReward();
      }
    },
  );
}

Fullscreen Video — One-off

try {
  final ad = await FullscreenAd.load(
    slotId: kFullscreenVideoId,
    iOS: const IOSFullscreenVideoConfig(slotId: kFullscreenVideoId),
    android: AndroidFullscreenVideoConfig(slotId: kFullscreenVideoId),
  );
  await ad.show(
    onEvent: (event) {
      if (event is AdClosedEvent) Navigator.pop(context);
    },
  );
} on AdLoadException catch (e) {
  debugPrint('load failed: $e');
}

Fullscreen Video — Preload Pool

await FullscreenAdPool.instance.configure(
  slotId: kFullscreenVideoId,
  iOS: const IOSFullscreenVideoConfig(slotId: kFullscreenVideoId),
  android: AndroidFullscreenVideoConfig(slotId: kFullscreenVideoId),
);

if (await FullscreenAdPool.instance.isReady(kFullscreenVideoId)) {
  await FullscreenAdPool.instance.show(slotId: kFullscreenVideoId);
}

Banner Ad

// BannerView auto-applies AspectRatio from expressSize — no wrapper needed
BannerView(
  iOS: IOSBannerConfig(
    slotId: kBannerId,
    expressSize: PangleExpressSize(width: 600, height: 260),
  ),
  android: AndroidBannerConfig(
    slotId: kBannerId,
    expressSize: PangleExpressSize(width: 600, height: 260),
  ),
  onClick: () {},
  onError: (code, msg) {},
  onRenderFail: (code, msg) {},
)

Feed Ad

// Step 1: load (returns ad IDs)
final PangleAd feedAd = await pangle.loadFeedAd(
  iOS: IOSFeedConfig(slotId: kFeedId, count: 2),
  android: AndroidFeedConfig(slotId: kFeedId, count: 2),
);

// Step 2: render each ID
FeedView(
  id: adId,                     // one of feedAd.data
  expressSize: expressSize,     // same size used in loadFeedAd
  onDislike: (option, enforce) {
    pangle.removeFeedAd([adId]); // clean up on dismiss
    setState(() {/* remove from list */});
  },
)

// Step 3: release on page dispose
@override
void dispose() {
  pangle.removeFeedAd(feedIds);
  super.dispose();
}

Feed Icon Ad (Android)

final PangleAd iconAd = await pangle.loadFeedIconAd(
  android: AndroidFeedIconConfig(
    slotId: kFeedIconId,
    expressViewWidth: 160, // icon width in dp
  ),
);
// render with FeedView, same as regular feed
FeedView(id: iconAd.data.first)

Draw Ad (Vertical Full-Screen Video)

// Step 1: load a batch
final PangleDrawAd drawAd = await pangle.loadDrawAd(
  iOS: IOSDrawConfig(slotId: kDrawId, adCount: 3),
  android: AndroidDrawConfig(slotId: kDrawId, adCount: 2),
);

// Step 2: display in a vertical PageView (TikTok-style)
PageView.builder(
  scrollDirection: Axis.vertical,
  itemCount: drawAd.data.length,
  itemBuilder: (context, i) => DrawView(
    id: drawAd.data[i],
    onClick: () {},
    onShow: () {},
    onRenderFail: (code, msg) {},
  ),
)

// Step 3: release when leaving the page
await pangle.removeDrawAd(drawAd.data);

Stream Ad (Custom Player)

// Load — returns video URL + metadata, no SDK view
final PangleStreamAd streamAd = await pangle.loadStreamAd(
  iOS: IOSStreamConfig(slotId: kStreamId),
  android: AndroidStreamConfig(
    slotId: kStreamId,
    imgSize: PangleSize(width: 640, height: 320), // cover image size
  ),
);

for (final StreamAdItem item in streamAd.data) {
  // item.videoUrl     — play this with your video player
  // item.imageUrl     — cover image
  // item.title        — ad title
  // item.description  — ad description
  // item.videoDuration — duration in seconds
  myPlayer.play(item.videoUrl!);
}

EcMall Ad (Shopping / Native Ad)

// Must be wrapped in a sized widget
SizedBox(
  width: 600,
  height: 257,
  child: EcMallView(
    slotId: kEcMallId,
    width: 600,
    height: 257,
    userData: null,   // optional Android JSON string for reward config
    onClick: () {},
    onShow: () {},
    onError: (code, msg) {},
  ),
)

Common Mistakes to Prevent

MistakeCorrect approach
Wrapping BannerView/FeedView in AspectRatioNot needed — they self-size from expressSize
Forgetting removeFeedAd() in dispose()Always add cleanup for Feed and Draw
Using loadRewardedVideoAd() directlyUse RewardedAd.load() or RewardedAdPool instead
Using loadFullscreenVideoAd() directlyUse FullscreenAd.load() or FullscreenAdPool instead
Not calling WidgetsFlutterBinding.ensureInitialized() before pangle.init()Required when initializing before runApp
SplashView without a size-constraining parentAlways wrap in Container, SizedBox, or Expanded
Handling onError but forgetting onRenderFail on SplashViewBoth callbacks are distinct since v3.0
Assuming close button auto-removes the viewIt does not since v3.

Content truncated.

When not to use it

  • When the user is not integrating ByteDance Pangle ads into a Flutter app
  • When the user does not need localized code comments
  • When the user is not working with the ad types supported by pangle_flutter

Limitations

  • The skill is for integrating ByteDance Pangle ads into a Flutter app.
  • The skill covers ad types supported by pangle_flutter.
  • The skill directs users to SETUP.md for Android Manifest and iOS Info.plist / CocoaPods setup.

How it compares

This skill provides localized, minimal, and runnable code for Pangle ad integration in Flutter, automatically adapting to the user's language for comments and handling various ad types, unlike generic ad integration guides.

Compared to similar skills

pangle-ad-integration side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
pangle-ad-integration (this skill)02moNo flagsBeginner
webf-native-plugin-dev27moReviewAdvanced
webf-native-plugins17moReviewAdvanced
cometchat-calls01moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

Search skills

Search the agent skills registry