Flutter Single Tag Implementation
Prerequisites
Do Flutter Get Started until finishing step 3.
Step summary
Add the Initialization code.
Add the Tagged Wrappers, Tagged Buttons
Note the Transitions Events
Add the testing Single Data
Test everything is working
Change everything to production code
Your app is now prepared for monetization with us.
Initialize the SDK
Use the R89SDK.initialize(...,singleTag: true)
method to initialize the SDK with enabled single tag functionality.
R89SDK.setLogLevel(LogLevel.debug); //This is for testing purposes, remove it on prod
R89SDK.setDebug(); //This is for testing purposes, remove it on prod
addTestingSingleTagData() /* This is a later step */
R89SDK.initialize(
publisherId: "TestRefinery89ID", /* This is for testing purposes, change it on prod */
appId: "TestDemoApp", /* This is for testing purposes, change it on prod */
singleTag: true);
Your publisherId
and appId
will be provided to you during onboarding process by email, you can also retrieve them from the web interface after login.
This appId
is not the same as the Manifest com.google.android.gms.ads.APPLICATION_ID
or the Info.plist
GADApplicationIdentifier
you used in the number 2 and 3 steps of Flutter Get Started.
Add navigation observer.
Just before starting to put R89Tag
widgets into your widget tree, make sure to add R89SDK.routeObserver
to your navigatorObservers
list.
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorObservers: [
R89SDK.routeObserver,
],
// ...
);
}
Tagged wrappers
The tagged wrapper is a widget inside which the ads will show. Use R89Tag
with the tag:
attribute set. You need to add R89Tag
s as many as you can, remember that placing a tagged wrapper does not mean we need to use it.
In the sample below two R89Tag
widgets are placed in a widget tree with predefined tags for banner banner_tag
and video outstream_tag
ads.
@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'),
// The outstream_tag will be replaced with the video outstream ad.
R89Tag(tag: 'outstream_tag'),
// ...
],
);
The R89Tag
wrapper can be used inside the scrollable widget as well.
@override
Widget build(BuildContext context) =>
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) =>
R89Tag(
// Provide a preconfigured tag.
tag: 'scroll_tag',
// Provide the item position
itemIndex: index,
child: ListTile(
leading: const Icon(
Icons.star_rounded,
color: Colors.amber,
),
title: Text(features[index % features.length]),
),
),
);
As you may notice, besides the tag
parameter, the itemIndex
is provided to R89Tag
, which is used by the R89SDK
to decide whether to display an ad for a given item position or not.
In a more enhanced scenario, If R89Tag
is used in multiple scrollable widgets on the same screen, a key
parameter needs to be specified for it, and the key
parameter should uniquely identify the scrollable widget. Use a ValueKey
to identify each scrollable widget.
@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"),
),
),
),
))),
],
),
);
In the sample above there are two scrollable widgets vertical and horizontal. The vertical one is a SliverList
and the other is a horizontal ListView
positioned at the index
3 inside the first SliverList
. As you can see, R89Tag
from the vertical SliverList
has a value key ValueKey('v_scroll')
and the other from the horizontal ListView
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.
With this added to your views we can detect that tag and place an ad inside of it if the single tag data says so.
Events
Events can trigger other formats, right now the single tag supports:
Transition events are detected by the single tag automatically by using the
R89SDK.routeObserver
after initialization. They happen when a navigation event occurs between two routes.Button Presses when the
R89Tag
widget detects anonTap
event inside its child baoundaries.
Example of transition:
class MainPage extends StatelessWidget {
...
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
...
ListTile(
...
onTap: () {
// Transition from the home MainPage to NewsPostDetailsPage.
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const NewsPostDetailsPage(),
// It's important to specify the destination route name.
settings: const RouteSettings(name: 'NewsPostDetailsPage')));
},
),
],
),
);
}
}
class NewsPostDetailsPage extends StatelessWidget {
...
}
It’s important to specify the destination RouteSettins(name:)
because the R89SDK uses the route name for transition tracking.
In this example an interstitial would be triggered when we see the NewsPostDetailsPage
comes to live after loading.
Example of button press:
With this button code, the R89Tag
will display an interstitial with the onTap
event on ListTile
, and as soon as the interstitial gets closed, the onTap
event will forwarded to ListTile
.
class MainPage extends StatefullWidget {
...
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
...
R89Tag(
tag: 'play_video_trailer_tag',
child: ListTile(
...
title: const Text('Play Video'),
// onTap will be called after closing the interstitial
onTap: () => playVideoTrailer(),
),
),
...
],
),
);
}
}
In this example an interstitial would be triggered when the button is pressed and when the interstitial is closed the playVideoTrailer()
method will be executed.
Adding testing single tag data
Go back to the point where the SDK was initialized at the start of the guide, we are going to test all the transitions, tagged wrappers, and tagged buttons you have placed in the app.
Before the initialization method, we called addTestingSingleTagData()
which uses the R89SDK.singleTagConfiguration
to add the testing data needed for debugging the Single Tag features.
More info in → Flutter How To Test Single Tag Implementation
When using the R89SDK.singleTagConfiguration
you are not going to be able to select the ad units that are for production, they are by default the testing config ids. Find the list of config Ids in Flutter - Ad Formats.
void addTestingSingleTagData() {
// Define the initial/home route name as the main screen,
// in the example it is MainPage
R89SDK.singleTagConfiguration.initialRouteName = '/'
// Configure the main screen with ad placements
R89SDK.singleTagConfiguration.addAdScreenConfig(
adScreenConfig: AdScreenConfig(screenName: '/')
// Add a banner inside the wrapper with the tag 'main_page_bottom_ad_container'
..addBanner(
tag: 'main_page_bottom_ad_container',
getAllWithTag: false, // Only place ad in the first R89Tag wrapper in the screen,
// in case there are multiple R89Tags with the same tag: available on the same screen.
wrapperRelativePositionAfter: true, // Place the ad below the child of R89Tag(child:...)
)
// Triggers an interstitial when transitioning from "MainPage" ("/") to "NewsPostDetailPage"
..addInterstitial(eventToTrack: 'NewsPostDetailPage')
// Triggers an interstitial when a child of R89Tag(tag:'play_video_trailer_tag',child:...) is pressed
..addInterstitial(eventToTrackButton: 'play_video_trailer_tag')
);
}
This step is for testing purposes and you are only going to see test ads when using this approach, but this is very helpful to us if you provide this peace of code to tell us where you want to place the ads.
Later when in production, this code will be removed and you have hopefully added flexible tagged wrappers and tagged all the button as possible so we can change your ad slots from the server without the need of updating the app.
Go into production
For going into production you will need to use your ids:
In the dart code remove the methods
R89SDK.setDebug()
andaddTestingSingleTagData()
.In the Android module change the
com.google.android.gms.ads.APPLICATION_ID
in the manifest for the production one.In the iOS module change the
GADApplicationIdentifier
in theinfo.plist
for the production one.In the dart code change the
appId
andpublisherId
in the initialization method for the production ones.it’s also recommended to remove
R89SDK.setLogLevel(LogLevels.DEBUG)
but not required.
How does it work?
We monitor your app to determine the active route/screen at any given moment. For each route/screen, we maintain a record of events and tags that you have supplied, enabling us to place ads in those tagged views or during specific transitions and events from the record.
We can display Display ads on tagged wrappers or trigger Interstitial ads during the transition from one screen to another or in button presses. And many other things All of this can be achieved without the need of coding specific triggers or manually adding the ad to the view. It is as simple as initializing the SDK.