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.zipInstalls 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.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
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:
- 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.
- Ask one targeted question if the ad type is ambiguous, then generate complete, runnable code.
- Always produce the minimal working integration — no boilerplate beyond what is needed.
Language Detection Rules
| User message language | Comment style |
|---|---|
| Chinese (any variant) | // 中文注释 |
| English | // English comment |
| Other language | Comment in that language |
Apply this rule to every code block you generate in this session, including follow-up responses.
Ad Type Catalogue
| Ad Type | Dart API | Widget |
|---|---|---|
| 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 | — |
| Banner | — | BannerView |
| Feed | pangle.loadFeedAd() | FeedView |
| Feed Icon | pangle.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
| Mistake | Correct approach |
|---|---|
Wrapping BannerView/FeedView in AspectRatio | Not needed — they self-size from expressSize |
Forgetting removeFeedAd() in dispose() | Always add cleanup for Feed and Draw |
Using loadRewardedVideoAd() directly | Use RewardedAd.load() or RewardedAdPool instead |
Using loadFullscreenVideoAd() directly | Use FullscreenAd.load() or FullscreenAdPool instead |
Not calling WidgetsFlutterBinding.ensureInitialized() before pangle.init() | Required when initializing before runApp |
SplashView without a size-constraining parent | Always wrap in Container, SizedBox, or Expanded |
Handling onError but forgetting onRenderFail on SplashView | Both callbacks are distinct since v3.0 |
| Assuming close button auto-removes the view | It 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.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| pangle-ad-integration (this skill) | 0 | 2mo | No flags | Beginner |
| webf-native-plugin-dev | 2 | 7mo | Review | Advanced |
| webf-native-plugins | 1 | 7mo | Review | Advanced |
| cometchat-calls | 0 | 1mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
webf-native-plugin-dev
openwebf
Develop custom WebF native plugins based on Flutter packages. Create reusable plugins that wrap Flutter/platform capabilities as JavaScript APIs. Use when building plugins for native features like camera, payments, sensors, file access, or wrapping existing Flutter packages.
webf-native-plugins
openwebf
Install WebF native plugins to access platform capabilities like sharing, payment, camera, geolocation, and more. Use when building features that require native device APIs beyond standard web APIs.
cometchat-calls
cometchat
Entry-point for adding CometChat Voice & Video Calling to any React, React Native, Angular, native Android, native iOS, or Flutter project. Detects the framework, picks standalone (calls-only) vs additive (calls on top of existing chat) mode, and routes to the per-family calls skill. Invoked by the
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
flutter-expert
sickn33
Master Flutter development with Dart 3, advanced widgets, and multi-platform deployment. Handles state management, animations, testing, and performance optimization for mobile, web, desktop, and embedded platforms. Use PROACTIVELY for Flutter architecture, UI implementation, or cross-platform features.
mobile-games
davila7
Mobile game development principles. Touch input, battery, performance, app stores.