Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. Add the Initialization code.

  2. Add the Application class to the Manifest (in case you are using it)Add the Tagged Wrappers, Tagged Buttons

  3. Note the Transitions Events

  4. Add the testing Single Data

  5. Test everything is working

  6. Change everything to production code

  7. Your app is now prepared for monetization with us.

...

Use the R89SDK.initialize(...,singleTag: true) method to initialize the SDK with enabled single tag functionality.

...

Info

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.

Note

This appID appId is not the same as the Manifest App Id com.google.android.gms.ads.APPLICATION_ID or the Info.plist GADApplicationIdentifier you used in previous steps.

Add navigation observer.

...

the number 2 and 3 steps of https://refinery89.atlassian.net/wiki/spaces/SDKpDocs/pages/1731100673/Flutter+Get+Started?atlOrigin=eyJpIjoiODVkNmU4N2E3ZWQ2NDJiY2IwYWY0YzE1MjRlMjRlYTAiLCJwIjoiYyJ9.

Add navigation observer.

Just before starting to put R89Tag widgets into your widget tree, make sure to add R89SDK.routeObserver to your navigatorObservers list.

Code Block
languagedart
@override
Widget build(BuildContext context) {
  return MaterialApp(
    navigatorObservers: [
      R89SDK.routeObserver,
    ],
    // ...
  );
}

Tagged wrappers

Tagged Wrappers are the containers The tagged wrapper is a widget inside which the ads will show, they are normal widgets, called . Use R89Tag with the tag: attribute set. You need to add R89Tags 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 pre-configured tag parameterspredefined tags for banner banner_tag and video outstream_tag ads.

Code Block
languagedart
@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 widget wrapper can be used inside the scrollable widget as well (such as ListView.builder).

Code Block
languagedart
  @override
  Widget build(BuildContext context) =>
      ListView.builder(
        itemCount: 100,
        itemBuilder: (context, index) =>
            R89Tag(
              // Provide a tag:preconfigured 'scroll_tag',.
              itemIndextag: index'scroll_tag',
              // child:Provide ListTile(the item position
              leadingitemIndex: index,
 const Icon(            child: ListTile(
     Icons.           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 SDK R89SDK to decide whether to display an ad for a given item position or not.

n In a more complex enhanced scenario, If R89Tag is used in multiple scrollable widgets on the same screen, a key parameter needs to be specified for it. The , and the key parameter should uniquely identifies identify the scrollable widget. Use the a ValueKey to identify the name of the each scrollable widget.In the sample below 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.

Code Block
Code Block
languagedart
  @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 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.

...

Events can trigger other formats, right now the single tag supports:

  • Transitions 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 an onTap event for inside its child for a specified tag: attributebaoundaries.

Example of transition:

Code Block
languagedart
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(),
                  // Specify It's important to specify the destination route name.
                  settings: const RouteSettings(name: 'NewsPostDetailsPage')));
            },
          ),
        ],
      ),
    );
  }
}

class NewsPostDetailsPage extends StatelessWidget {
  ...
}
Info
In this example an interstitial
Tip

It’s important to specify the destination RouteSettins(name:)because the R89SDK uses the route name for transition tracking.

Info

In this example an interstitial would be triggered when we see the NewsPostDetailsPage comes to live after loading.

...

Example of button press:

with 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.

Code Block
languagedart
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(),
            ),
          ),
          ...
        ],
      ),
    );
  }
}

...

Before the initialization method, we called addTestingSingleTagData() which uses the R89SDK.singleTagConfiguration to add the testing data needed for debugging the SDKSingle Tag features.

More info in → Flutter How To Test Single Tag Implementation

Note

When using the SingleTagConfigBuilder 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 id config ids. Find the list of config Ids in Flutter - Ad Formats.

Code Block
languagedart
void addTestingSingleTagData() {
  R89SDK.singleTagConfiguration  
    // Define the initial/home route name as the main screen, 
   ..initialRouteName = // 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, // Only use the first tagged wrapper in "/" 
                                      // in case there are multiple R89Tags with the same tag: available on the same screen.
                wrapperRelativePositionAfter: true, // Place the ad afterbelow the child of R89Tag(child:...)
          )
          // TriggerTriggers an interstitial when transitioning from "MainPage" ("/") to "NewsPostDetailPage"
          ..addInterstitial(eventToTrack: 'NewsPostDetailPage')
          // TriggerTriggers an interstitial when a child of R89Tag(tag:'play_video_trailer_tag',child:...) is pressed
          ..addInterstitial(eventToTrackButton: 'play_video_trailer_tag')
    );
}

...

For going into production you will need to use your ids:

  • Remove In the dart code remove the methods R89SDK.setDebug() and addTestingSingleTagData().

  • Change In the Android module change the App ID in the manifest for the production one.

  • Change In the iOS module change the GADApplicationIdentifier in the info.plist for the production one.

  • Change In the dart code change the appId and publisherId in the initialization method for the production ones.

  • it’s also recommended to remove R89SDK.setLogLevel(LogLevels.DEBUG) but not neededrequired.

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 have the capability to can display Display ads on a tagged wrappers or trigger an Interstitial ads during the transition from one screen to another or in button presspresses. 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.

...