Skip to content

Commit a9b0475

Browse files
committed
feat(ads): enhance ad visibility control with user role and slot type
- Add userRole parameter to getFeedAd, getInterstitialAd, and getInArticleAd methods - Implement role-based visibility checks for feed, interstitial, and in-article ads - Introduce slotType parameter for in-article ads to enable targeted ad slots - Refactor ad loading logic to respect global, role-based, and slot-based enablement settings - Update method signatures and documentation to reflect new parameters and functionality
1 parent 25d8992 commit a9b0475

File tree

1 file changed

+61
-13
lines changed

1 file changed

+61
-13
lines changed

lib/ads/ad_service.dart

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class AdService {
5656
Future<void> disposeAd(dynamic adModel) async {
5757
// Determine the AdPlatformType from the adModel if it's an InlineAd or InterstitialAd.
5858
AdPlatformType? providerType;
59-
Object? adObject; // To hold the actual ad object
59+
Object? adObject;
6060

6161
if (adModel is InlineAd) {
6262
providerType = adModel.provider;
@@ -69,7 +69,7 @@ class AdService {
6969
if (providerType != null && adObject != null) {
7070
final adProvider = _adProviders[providerType];
7171
if (adProvider != null) {
72-
await adProvider.disposeAd(adObject); // Pass the actual ad object
72+
await adProvider.disposeAd(adObject);
7373
} else {
7474
_logger.warning(
7575
'AdService: No AdProvider found for type $providerType to dispose ad.',
@@ -95,10 +95,12 @@ class AdService {
9595
/// - [adThemeStyle]: UI-agnostic theme properties for ad styling.
9696
/// - [headlineImageStyle]: The user's preference for feed layout,
9797
/// which can be used to request an appropriately sized ad.
98+
/// - [userRole]: The current role of the user, used to determine ad visibility.
9899
Future<InlineAd?> getFeedAd({
99100
required AdConfig adConfig,
100101
required AdType adType,
101102
required AdThemeStyle adThemeStyle,
103+
required AppUserRole userRole,
102104
HeadlineImageStyle? headlineImageStyle,
103105
}) async {
104106
_logger.info('AdService: getFeedAd called for adType: $adType');
@@ -108,6 +110,7 @@ class AdService {
108110
adThemeStyle: adThemeStyle,
109111
feedAd: true,
110112
headlineImageStyle: headlineImageStyle,
113+
userRole: userRole,
111114
);
112115
}
113116

@@ -116,25 +119,37 @@ class AdService {
116119
/// This method delegates the ad loading to the appropriate [AdProvider]
117120
/// based on the [adConfig]'s `primaryAdPlatform`. It is specifically
118121
/// designed for interstitial ads that are displayed as full-screen overlays,
119-
/// typically triggered on route changes.
122+
/// typically on route changes.
120123
///
121124
/// Returns an [InterstitialAd] if an interstitial ad is available, otherwise `null`.
122125
///
123126
/// - [adConfig]: The remote configuration for ad display rules.
124127
/// - [adThemeStyle]: UI-agnostic theme properties for ad styling.
128+
/// - [userRole]: The current role of the user, used to determine ad visibility.
125129
Future<InterstitialAd?> getInterstitialAd({
126130
required AdConfig adConfig,
127131
required AdThemeStyle adThemeStyle,
132+
required AppUserRole userRole,
128133
}) async {
129134
_logger.info('AdService: getInterstitialAd called.');
130135
if (!adConfig.enabled) {
131136
_logger.info('AdService: Ads are globally disabled in RemoteConfig.');
132137
return null;
133138
}
134139

135-
// Check if interstitial ads are enabled in the remote config.
136-
if (!adConfig.interstitialAdConfiguration.enabled) {
137-
_logger.info('AdService: Interstitial ads are disabled in RemoteConfig.');
140+
// Check if interstitial ads are enabled for the current user role.
141+
final interstitialConfig = adConfig.interstitialAdConfiguration;
142+
// Check if the interstitial ads are globally enabled AND if the current
143+
// user role has a defined configuration in the visibleTo map.
144+
final isInterstitialEnabledForRole =
145+
interstitialConfig.enabled &&
146+
interstitialConfig.visibleTo.containsKey(userRole);
147+
148+
if (!isInterstitialEnabledForRole) {
149+
_logger.info(
150+
'AdService: Interstitial ads are disabled for user role $userRole '
151+
'or globally in RemoteConfig.',
152+
);
138153
return null;
139154
}
140155

@@ -216,17 +231,23 @@ class AdService {
216231
///
217232
/// - [adConfig]: The remote configuration for ad display rules.
218233
/// - [adThemeStyle]: UI-agnostic theme properties for ad styling.
234+
/// - [userRole]: The current role of the user, used to determine ad visibility.
235+
/// - [slotType]: The specific in-article ad slot type.
219236
Future<InlineAd?> getInArticleAd({
220237
required AdConfig adConfig,
221238
required AdThemeStyle adThemeStyle,
239+
required AppUserRole userRole,
240+
required InArticleAdSlotType slotType,
222241
}) async {
223242
_logger.info('AdService: getInArticleAd called.');
224243
return _loadInlineAd(
225244
adConfig: adConfig,
226-
adType: AdType.banner, // In-article ads are now always banners
245+
adType: AdType.banner,
227246
adThemeStyle: adThemeStyle,
228247
feedAd: false,
229248
bannerAdShape: adConfig.articleAdConfiguration.bannerAdShape,
249+
userRole: userRole,
250+
slotType: slotType,
230251
);
231252
}
232253

@@ -243,30 +264,57 @@ class AdService {
243264
/// - [headlineImageStyle]: The user's preference for feed layout,
244265
/// which can be used to request an appropriately sized ad.
245266
/// - [bannerAdShape]: The preferred shape for banner ads, used for in-article banners.
267+
/// - [userRole]: The current role of the user, used to determine ad visibility.
268+
/// - [slotType]: The specific in-article ad slot type, used for in-article ads.
246269
///
247270
/// Returns an [InlineAd] if an ad is successfully loaded, otherwise `null`.
248271
Future<InlineAd?> _loadInlineAd({
249272
required AdConfig adConfig,
250273
required AdType adType,
251274
required AdThemeStyle adThemeStyle,
252275
required bool feedAd,
276+
required AppUserRole userRole,
253277
HeadlineImageStyle? headlineImageStyle,
254278
BannerAdShape? bannerAdShape,
279+
InArticleAdSlotType? slotType,
255280
}) async {
256281
_logger.info(
257282
'AdService: _loadInlineAd called for adType: $adType, feedAd: $feedAd',
258283
);
259-
// Check if ads are globally enabled and specifically for the context (feed or article).
284+
// Check if ads are globally enabled.
260285
if (!adConfig.enabled) {
261286
_logger.info('AdService: Ads are globally disabled in RemoteConfig.');
262287
return null;
263288
}
264-
if (feedAd && !adConfig.feedAdConfiguration.enabled) {
265-
_logger.info('AdService: Feed ads are disabled in RemoteConfig.');
266-
return null;
289+
290+
// Check if ads are enabled for the specific context and user role.
291+
var isContextEnabled = false;
292+
if (feedAd) {
293+
final feedAdConfig = adConfig.feedAdConfiguration;
294+
// Check if feed ads are globally enabled AND if the current user role
295+
// has a defined configuration in the visibleTo map.
296+
isContextEnabled =
297+
feedAdConfig.enabled && feedAdConfig.visibleTo.containsKey(userRole);
298+
} else {
299+
// For in-article ads, check global article ad enablement and then
300+
// specific slot enablement for the user role.
301+
final articleAdConfig = adConfig.articleAdConfiguration;
302+
final isArticleAdEnabledForRole = articleAdConfig.visibleTo.containsKey(
303+
userRole,
304+
);
305+
final isSlotEnabledForRole =
306+
articleAdConfig.visibleTo[userRole]?[slotType] ?? false;
307+
isContextEnabled =
308+
articleAdConfig.enabled &&
309+
isArticleAdEnabledForRole &&
310+
isSlotEnabledForRole;
267311
}
268-
if (!feedAd && !adConfig.articleAdConfiguration.enabled) {
269-
_logger.info('AdService: In-article ads are disabled in RemoteConfig.');
312+
313+
if (!isContextEnabled) {
314+
_logger.info(
315+
'AdService: Ads are disabled for current context (feedAd: $feedAd, '
316+
'slotType: $slotType) and user role $userRole in RemoteConfig.',
317+
);
270318
return null;
271319
}
272320

0 commit comments

Comments
 (0)