refinery89_monetize_app 1.0.0-dev.1 refinery89_monetize_app: ^1.0.0-dev.1 copied to clipboard
The flutter plugin for the Refinery 89 Monetize App, supporting banner, outStream, interstitial (full-screen) and scrollable ads
Refinery89 Monetize App SDK #
This repository contains the source code for the Refinery89 Monetize App Flutter plugin, which enables publishers to monetize Flutter apps.
Get Started #
1. Add “Refinery89 Monetize App“ dependency by running
flutter pub add refinery89_monetize_app
2. Android & iOS Platform Configurations
2.1 Android Configuration
Prerequisites
- Use Android Studio 3.2 or higher.
- minSdkVersion of 19 or higher.
- compileSdkVersion of 28 or higher.
2.1.1 Gradle Dependencies
Add maven { url = uri("https://jitpack.io") }
to project level build.gradle:
allprojects {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
2.2.2 Add Google Ad ID to Manifext.xml
<manifest>
<application>
<!-- The value is the test id from Google ad manager docs -->
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value=
<the-google-id>/>
...
<activity
...>
...
</activity>
</application>
</manifest>
Attention For countries that require to request CMP consent from users before displaying ads,
please add @style/Theme.AppCompat.NoActionBar
theme to the application
's theme
tag in the Manifest.xml file,
otherwise SDK will crash on initialization while trying to display CMP request activity.
<manifest>
<application>
...
android:theme="@style/Theme.AppCompat.NoActionBar"
...>
...
</application>
</manifest>
-
Test: Use "ca-app-pub-3940256099942544~3347511713" for
-
Production: Use your own Google Id provided by us for
2.2 iOS Configuration
According to Google Ads documentation update Info.plist file to add following two keys:
- A
GADApplicationIdentifier
key with a string value of your AdMob app ID found in the AdMob UI. - A
SKAdNetworkItems
key withSKAdNetworkIdentifier
values for Google (cstr6suwn9.skadnetwork) and select third-party buyers who have provided these values to Google.
3. Flutter Auto Configuration
The auto configuration let publishers to place advertisements throughout the app which are later can be dynamically configured from the dashboard (TODO Ask what is the dashboard name).
Below are the dynamic features offered by the auto configuration
- Interstitial ads in between screen transitions.
- Display banner and video outstream ads.
- Automatically display interstitial ads on content tap events.
- Dynamically add banner and outstream ads inside the scrollable widgets.
The steps below are demonstrating how to configure the R89SDK
in the auto-configuration mode and configure single-tag locally.
3.1 Add the R89SDK.routeObserver to navigatorObservers.
The R89SDK
uses the navigatorObservers
to properly destroy ads when the screen closes
and to track the route transitions to display interstitial ads if configured.
@override
Widget build(BuildContext context) {
return MaterialApp(
//...
navigatorObservers: [
R89SDK.routeObserver,
],
// ...
);
}
3.2 Initialize the R89SDK in auto-configuration mode.
Before calling the R89SDK.initialize(...,singleTag: true)
method The configSingleTag()
method locally configures the single-tag configuration for each screen.
@override
void initializeSDK() {
// Before initializing the R89SDK,
// do the single tag local configurations
// Note that the local configurations will be used as
// getLocalFakeData is specified true in the R89SDK.setDebug method below.
// The configSingleTag() is only needed to have local single-tag configuration.
configSingleTag();
R89SDK.setLogLevel(LogLevel.debug);
// With debug enabled the SDK will fetch the built-in mocked data for testing.
R89SDK.setDebug(getLocalFakeData: true);
// Starting the auto-configuration initialization
R89SDK.initialize(
publisherId: "TestRefinery89ID",
appId: "TestDemoApp",
// if true enables the auto-configuration mode
singleTag: true);
}
The singleTag: true
initializes the R89SDK
in the auto-configuration mode.
In the example below AdScreenConfig
is added to display an interstitial ad when user navigates form
the initial route '/'
to the FeaturesList
screen.
void configSingleTag() {
// Predefined local test configIds from the R89SDK. Use them for the local testing
const interstitialR89ConfigId = ConfigBuilder.interstitialTestR89ConfigId;
// Starts the single-tag configuration.
R89SDK.singleTagConfiguration
// Specifies the initial route name, which by default is '/'.
..initialRouteName = '/'
// Configures AdScreenConfig for the '/' route, and creates tags for
// banner, outstream, button interstitial and transition interstitials.
..addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: '/')
// This configs an interstitial ad to be displayed when navigating from the root '/' route to the FeaturesList
..addInterstitial(r89ConfigId: interstitialR89ConfigId, eventToTrack: 'FeaturesList')
);
}
Provide the route settings name as FeaturesList
while navigating from the initial route screen "/"
to the FeaturesList
void navigateToFeaturesList() {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const FeaturesList(),
// Providing the route name
settings: const RouteSettings(name: 'FeaturesList')));
}
In is important to provide the route settings name while making the navigation, because R89SDK
uses the RouteSettings
's name
parameter to track
the route transitions.
Now the interstitial ad will be automatically displayed whenever user navigates from the initial route to the FeaturesList
route.
3.3 Display Banner and Outstream ads.
To start with a Banner
, add a banner ad configuration to the configSingleTag()
method.
void configSingleTag() {
// Predefined local test configIds from the R89SDK. Use them for the local testing
const bannerR89ConfigId = ConfigBuilder.bannerTestR89ConfigId;
// Starts the single-tag configuration.
R89SDK.singleTagConfiguration
// Specifies the initial route name, which by default is '/'.
..initialRouteName = '/'
// Configures AdScreenConfig for the '/' route, and creates tags for
// banner, outstream, button interstitial and transition interstitials.
..addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: '/')
// This configs a banner ad to be substituted in all places (because getAllWithTag:true)
// where R89Tag with 'banner_tag' is specified in the 'BannerTagsScreen'
..addBanner(r89ConfigId: bannerR89ConfigId, tag: 'banner_tag', getAllWithTag: true,
wrapperRelativePositionAfter: true)
// ..addInterstitial(...)
);
}
The tags named banner_tag
can be placed inside the initial route's widget tree.
Use R89Tag(tag: 'banner_tag')
widget to place the banner_tag
tag in to the widget tree
so it can later be automatically replaced with Banner
ad by the SDK.
// Inside the initial '/' route widget tree.
@override
Widget build(BuildContext context) =>
const Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// ...
// The banner_tag will be replaced with the Banner ad.
R89Tag(tag: 'banner_tag'),
// ...
],
);
Note that the R89Tag
widget can take a child as parameter. In that case the ad will be positioned before or after the child widget,
in accordance to wrapperRelativePositionAfter
parameter's value, which is specified inside the configSingleTag()
method for the banner_tag
configuration.
The getAllWithTag: true
parameter specified inside the configSingleTag()
method, will place Banner
ad for all specified tags on the screen named as banner_tag
,
otherwise if specified getAllWithTag: false
only the first tag named banner_tag
will display a banner ad, the others with the same tag banner_tag
will be ignored or display
the child if provided.
Similar to addBanner
method, use the addOutstream
to configure a tag that displays a video outstream.
Add a configuration for a video outstream to configSingleTag()
method.
void configSingleTag() {
// Predefined local test configIds from the R89SDK. Use them for the local testing
const outStreamR89ConfigId = ConfigBuilder.videoOutStreamTestR89ConfigId;
// Starts the single-tag configuration.
R89SDK.singleTagConfiguration
// Specifies the initial route name, which by default is '/'.
..initialRouteName = '/'
// Configures AdScreenConfig for the '/' route, and creates tags for
// banner, outstream, button interstitial and transition interstitials.
..addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: '/')
// This configs a outstream ad to be substituted for the first (because getAllWithTag:false)
// R89Tag with 'outstream_tag' is specified.
..addOutStream(
r89ConfigId: outStreamR89ConfigId, tag: 'outstream_tag', getAllWithTag: false,
wrapperRelativePositionAfter: true) // will be placed after the child, if child is provided
// ... addBanner(...)
// ... addInterstitial(...)
);
}
Use R89Tag
widget to place the outstream_tag
tag in to the widget tree.
// Inside the initial '/' route widget tree.
@override
Widget build(BuildContext context) =>
const Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// ...
// The outstream_tag will be replaced with the video outstream ad.
R89Tag(tag: 'outstream_tag'),
// The banner_tag will be replaced with the banner ad.
R89Tag(tag: 'banner_tag'),
// ...
],
);
For both cases, the banner or the video outstream, R89Tag
widget are used to place a configured tag in to the widget tree, those
are later will be replace with the appropriate advertisement by the R89SDK
.
3.4 Display interstitial ad on tap event.
The R89Tag
can take a child as a parameter, and display an interstitial first when user taps on provided child's content,
then propagate the on tap event down to child.
The example below outlines the configuration for the button_tag
for the initial route
to display an interstitial when it detects a tap event on it's child's content.
void configSingleTag() {
//...
const interstitialR89ConfigId = ConfigBuilder.interstitialTestR89ConfigId;
R89SDK.singleTagConfiguration
..initialRouteName = '/'
//...
..addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: '/')
// ...addBanner(...)
// ...addOutstream(...)
// ...addInterstitial(...)
// This configures an interstitial that will show when user taps on content which is wrapped with
// R89Tag(tag: 'button_tag', child: button())
..addInterstitial(
r89ConfigId: interstitialR89ConfigId, eventToTrackButton: 'button_tag')
);
}
The R89Tag
will intercept child's tap event, display an interstitial, and run the child's onTap callback when the interstitial get closed.
// Inside the initial screen.
@override
Widget build(BuildContext context) =>
const Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// ...
// The button_tag will wrap the child content and intercept the on tap events on it to display an interstitial,
// and will invoke child's onTap event after the interstitial get closed.
R89Tag(
tag: 'button_tag',
child: ListTile(
// ...
// The onTap will be invoked right after the interstitial ad get closed.
onTap: () {
// This Scaffold will be displayed after the interstitial get closed.
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content:
Text('This SnackBar is displayed after the interstitial get closed.')));
},
)
)
,
// ...
]
,
);
3.5 Add R89Tag to scrollable widgets.
The R89Tag
widget can be used inside the scrollable widget as well (such as ListView.builder
).
Here is how to configure it for the FeaturesList
screen.
void configSingleTag() {
//...
const interstitialR89ConfigId = ConfigBuilder.interstitialTestR89ConfigId;
R89SDK.singleTagConfiguration
..initialRouteName = '/'
//...
..addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: 'FeaturesList')
// ...
// This configures the scroll_tag for the scrollable widgets
..addInfiniteScroll(r89ConfigId: infiniteScrollR89ConfigId, tag: 'scroll_tag'));
}
The scroll_tag
tag now can be used with R89Tag
widget inside the ListView
.
class FeaturesList extends StatelessWidget {
const FeaturesList({super.key});
@override
Widget build(BuildContext context) =>
ListView.builder(
itemCount: 100,
shrinkWrap: true,
itemBuilder: (context, index) =>
R89Tag(
tag: 'scroll_tag',
itemIndex: index,
child: ListTile(
leading: const Icon(
Icons.star_rounded,
color: Colors.amber,
),
title: Text(features[index % features.length]),
),
),
);
}
As you may notice, this time, besides the tag
, the extra parameter itemIndex
is provided to R89Tag
.
The itemIndex
is used by the SDK to decide whether to display an ad for a given position or not.
3.6 Add R89Tag to multiple scrollable widgets.
The R89Tag
needs a key
parameter specified, if it is used in multiple scrollable widgets on the same screen.
The key
parameter in this case uniquely identifies the scrollable widget.
Use the ValueKey
to identify the name of the scrollable widget.
In the sample below there are two scrollable widgets, one is a vertical SliverList
and the other is horizontal ListView
positioned at the index = 3
in the first SliverList
.
@override
Widget build(BuildContext context) =>
Scaffold(
body: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
childCount: 40,
(context, index) =>
index != 3
? R89Tag(
key: const ValueKey('v_scroll'),
tag: 'infinite_scroll',
itemIndex: index,
child: Text("Item $index"))
: KeepAliveWrapper(
child: SizedBox(
height: 400,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 40,
itemBuilder: (context, index) =>
R89Tag(
key: const ValueKey('h_scroll'),
tag: 'infinite_scroll',
itemIndex: index,
child: Text("Item $index"),
),
),
),
))),
],
),
);
The R89Tag
from the vertical list has a value key ValueKey('v_scroll')
and the other from the horizontal list has ValueKey('h_scroll')
.
Those keys are used by the R89SDK
to separate the scrollable widgets and apply the ad placement logic separately for each of them.
Auto-configuration Summary
There are 4 types of ad configurations available for AdScreenConfig
in the auto-configuration mode.
addInterstitial
will configure theR89SDK
to displayInterstitial
ad on route transitions or when user taps on a button.addBanner
will configure theR89SDK
to display aBanner
ad for a specifiedtag
in the widget tree.addOutStream
will configure theR89SDK
to display aOutstream
ad for a specifiedtag
in the widget tree.addInfiniteScroll
will configure theR89SDK
to display aBanner
andOutstream
ads inside the scrollable widget, such asListView
.
Please check the example app for the full implementation of the auto-configuration.
4. Initialize the R89SDK in manual-configuration mode.
4.1 Add the R89SDK.routeObserver to Navigator
Add the R89SDK.routeObserver
to list of navigatorObservers
.
@override
Widget build(BuildContext context) {
return MaterialApp(
// ...
navigatorObservers: [
R89SDK.routeObserver,
],
// ...
);
}
4.2 Initialize R89SDK in manual-config mode.
@override
void initState() {
super.initState();
R89SDK.setLogLevel(LogLevel.debug);
// With debug enabled the SDK will fetch the built-in mocked data for testing.
R89SDK.setDebug();
// auto-configuration initialization
R89SDK.initialize(
publisherId: "TestRefinery89ID",
appId: "TestAutoConfigDemoApp");
}
For manual-config initialization details check the example app.
4.3 Display Ads in manual-config mode.
R89SDK supports the following ad formats
AdFormat.banner
Rectangular advertisements that remain visible on the screen during user interaction with the application, and have the ability to refresh automatically after a specified duration.AdFormat.videoOutStreamBanner
Video ads within a banner, that stay on the screen as users interact with the app, refreshing automatically after a certain period.AdFormat.interstitial
Full-screen ads that appear until the user closes. They're best used at natural pauses in the flow of an app's execution, such as in between levels of a game or screen-to-screen navigation.AdFormat.infiniteScroll
Ads load dynamically as users scroll through content, and dynamically display banner or videoOutStreamBanner ads based on the item's position within the scroll view.
4.3.1 Banner ads in manual-config mode.
Use the R89Banner
widget to Display a banner ad.
@override
Widget build(BuildContext context) =>
Scaffold(
// appBar: ...,
body: Column(children: [
// ...
R89Banner(
configurationId: ConfigBuilder.bannerTestR89ConfigId),
// ...
],),
);
4.3.2 OutStream ads in manual-config mode.
Use the R89OutStream
widget to Display a video ad.
@override
Widget build(BuildContext context) =>
Scaffold(
// appBar: ...,
body: Column(children: [
// ...
R89OutStream(
configurationId: ConfigBuilder.videoOutStreamTestR89ConfigId),
// ...
],),
);
4.3.3 Interstitial ads in manual-config mode.
Use the createInterstitial
method from RefineryAdFactory
to display interstitial ads by providing the configurationId
R89SDK.adFactory.createInterstitial(configurationId:ConfigBuilder.interstitialTestR89ConfigId);
Use the R89InfiniteScrollAd
widget to display ads by index in the scrollable widgets.
In the ListView
's item add R89InfiniteScrollAd
as follows
Widget _buildItem(context, index) =>
Card(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Item index $index"),
),
Center(
child: R89InfiniteScrollAd(
itemIndex: index, infiniteScrollId: infiniteScrollId),
)
],
),
);
R89InfiniteScrollAd has two required parameters
itemIndex
the item position in the ListViewinfiniteScrollId
is the R89SDK-generated scroll Id, which is shared between the child items of the same ListView.
Here is an example on how to generate infiniteScrollId
final int infiniteScrollId = R89SDK.adFactory.createInfiniteScroll(
configurationId: ConfigConstants.infiniteScrollTestR89ConfigId);
The Full example for scrollable ads.
import 'package:flutter/material.dart';
import 'package:playground/config_constants.dart';
import 'package:refinery89_monetize_app/r89_sdk.dart';
class ScrollPage extends StatefulWidget {
const ScrollPage({super.key});
@override
State<ScrollPage> createState() => _ScrollPageState();
}
class _ScrollPageState extends State<ScrollPage> {
final int infiniteScrollId = R89SDK.adFactory.createInfiniteScroll(
configurationId: ConfigConstants.infiniteScrollTestR89ConfigId);
@override
Widget build(BuildContext context) =>
ListView.builder(
itemCount: 500,
itemBuilder: (context, index) => _buildItem(context, index),
);
Widget _buildItem(context, index) =>
Card(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Item index $index"),
),
Center(
child: R89InfiniteScrollAd(
itemIndex: index, infiniteScrollId: infiniteScrollId),
)
],
),
);
}
Support #
Feel free to reach out to our support team if you encounter any problems.