Skip to content

Commit

Permalink
AdSense Ad Placement API initial version
Browse files Browse the repository at this point in the history
(This is a cherry-pick of PR flutter#7747)
  • Loading branch information
astivi authored and ditman committed Dec 4, 2024
1 parent 49a7a75 commit fe8cf05
Show file tree
Hide file tree
Showing 16 changed files with 558 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ packages/flutter_template_images/** @stuartmorgan
packages/go_router/** @chunhtai
packages/go_router_builder/** @chunhtai
packages/google_adsense/** @sokoloff06
packages/google_adsense_ad_placement_api_web/** @astivi
packages/google_identity_services_web/** @ditman
packages/google_maps_flutter/** @stuartmorgan
packages/google_sign_in/** @stuartmorgan
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ These are the packages hosted in this repository:
| [go\_router](./packages/go_router/) | [![pub package](https://img.shields.io/pub/v/go_router.svg)](https://pub.dev/packages/go_router) | [![pub points](https://img.shields.io/pub/points/go_router)](https://pub.dev/packages/go_router/score) | [![popularity](https://img.shields.io/pub/popularity/go_router)](https://pub.dev/packages/go_router/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20go_router?label=)](https://github.com/flutter/flutter/labels/p%3A%20go_router) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20go_router?label=)](https://github.com/flutter/packages/labels/p%3A%20go_router) |
| [go\_router\_builder](./packages/go_router_builder/) | [![pub package](https://img.shields.io/pub/v/go_router_builder.svg)](https://pub.dev/packages/go_router_builder) | [![pub points](https://img.shields.io/pub/points/go_router_builder)](https://pub.dev/packages/go_router_builder/score) | [![popularity](https://img.shields.io/pub/popularity/go_router_builder)](https://pub.dev/packages/go_router_builder/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20go_router_builder?label=)](https://github.com/flutter/flutter/labels/p%3A%20go_router_builder) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20go_router_builder?label=)](https://github.com/flutter/packages/labels/p%3A%20go_router_builder) |
| [google\_adsense](./packages/google_adsense/)| [![pub package](https://img.shields.io/pub/v/google_adsense.svg)](https://pub.dev/packages/google_adsense) | [![pub points](https://img.shields.io/pub/points/google_adsense)](https://pub.dev/packages/google_adsense/score) | [![popularity](https://img.shields.io/pub/popularity/google_adsense)](https://pub.dev/packages/google_adsense/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_adsense?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_adsense) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_adsense?label=)](https://github.com/flutter/packages/labels/p%3A%20google_adsense) |
| [google\_adsense\_ad\_placement\_api\_web](./packages/google_adsense_ad_placement_api_web/)| [![pub package](https://img.shields.io/pub/v/google_adsense_ad_placement_api_web.svg)](https://pub.dev/packages/google_adsense_ad_placement_api_web)| [![pub points](https://img.shields.io/pub/points/google_adsense_ad_placement_api_web)](https://pub.dev/packages/google_adsense_ad_placement_api_web/score)| [![popularity](https://img.shields.io/pub/popularity/google_adsense_ad_placement_api_web)](https://pub.dev/packages/google_adsense_ad_placement_api_web/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_adsense_ad_placement_api_web?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_adsense_ad_placement_api_web) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_adsense_ad_placement_api_web?label=)](https://github.com/flutter/packages/labels/p%3A%20google_adsense_ad_placement_api_web) |
| [google\_maps\_flutter](./packages/google_maps_flutter/) | [![pub package](https://img.shields.io/pub/v/google_maps_flutter.svg)](https://pub.dev/packages/google_maps_flutter) | [![pub points](https://img.shields.io/pub/points/google_maps_flutter)](https://pub.dev/packages/google_maps_flutter/score) | [![popularity](https://img.shields.io/pub/popularity/google_maps_flutter)](https://pub.dev/packages/google_maps_flutter/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20maps?label=)](https://github.com/flutter/flutter/labels/p%3A%20maps) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_maps_flutter?label=)](https://github.com/flutter/packages/labels/p%3A%20google_maps_flutter) |
| [google\_sign\_in](./packages/google_sign_in/) | [![pub package](https://img.shields.io/pub/v/google_sign_in.svg)](https://pub.dev/packages/google_sign_in) | [![pub points](https://img.shields.io/pub/points/google_sign_in)](https://pub.dev/packages/google_sign_in/score) | [![popularity](https://img.shields.io/pub/popularity/google_sign_in)](https://pub.dev/packages/google_sign_in/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20google_sign_in?label=)](https://github.com/flutter/flutter/labels/p%3A%20google_sign_in) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20google_sign_in?label=)](https://github.com/flutter/packages/labels/p%3A%20google_sign_in) |
| [image\_picker](./packages/image_picker/) | [![pub package](https://img.shields.io/pub/v/image_picker.svg)](https://pub.dev/packages/image_picker) | [![pub points](https://img.shields.io/pub/points/image_picker)](https://pub.dev/packages/image_picker/score) | [![popularity](https://img.shields.io/pub/popularity/image_picker)](https://pub.dev/packages/image_picker/score) | [![GitHub issues by-label](https://img.shields.io/github/issues/flutter/flutter/p%3A%20image_picker?label=)](https://github.com/flutter/flutter/labels/p%3A%20image_picker) | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr/flutter/packages/p%3A%20image_picker?label=)](https://github.com/flutter/packages/labels/p%3A%20image_picker) |
Expand Down
6 changes: 6 additions & 0 deletions packages/google_adsense_ad_placement_api_web/AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Below is a list of people and organizations that have contributed
# to the Process project. Names should be added to the list like so:
#
# Name/Organization <email address>

Google Inc.
3 changes: 3 additions & 0 deletions packages/google_adsense_ad_placement_api_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

* Initial version
25 changes: 25 additions & 0 deletions packages/google_adsense_ad_placement_api_web/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Copyright 2013 The Flutter Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 changes: 36 additions & 0 deletions packages/google_adsense_ad_placement_api_web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# google_adsense_ad_placement_api_web

Wrapper of the AdSense Ad Placement API to be used in Dart and Flutter apps.
This Wrapper targets only the WEB platform.

## Features

To view the complete API, please check the official [AdSense website](https://developers.google.com/ad-placement/apis)

## Getting started

Add this package as a dependency on `pubspec.yaml` and import the library and the `ad_placement_api.dart` file.
This package supports interacting with the Ad Placement API after it's already loaded. Please remember to include the appropriate adsense js files to the page before using this package.


## Usage

When you import the library inside a file, you'll have access to the singleton object `adPlacementApi`, which will have wrappers to both of the global functions that the Ad Placement API exposes: adBreak and adConfig.

Example:
<?code-excerpt "example/lib/main.dart (main-example)"?>
```dart
import 'package:google_adsense_ad_placement_api_web/google_adsense_ad_placement_api_web.dart';
void main() {
adPlacementApi.adBreak(
name: 'rewarded-example',
type: BreakType.reward,
);
}
```

## Testing

Use `dart run script/tool/bin/flutter_plugin_tools.dart test --packages google_adsense_ad_placement_api_web --platform chrome` to test.
You need to specify a web platform to be able to test the JS Interop library.
14 changes: 14 additions & 0 deletions packages/google_adsense_ad_placement_api_web/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// #docregion main-example
import 'package:google_adsense_ad_placement_api_web/google_adsense_ad_placement_api_web.dart';

void main() {
adPlacementApi.adBreak(
name: 'rewarded-example',
type: BreakType.reward,
);
}
// #enddocregion main-example
21 changes: 21 additions & 0 deletions packages/google_adsense_ad_placement_api_web/example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: google_adsense_ad_placement_api_web_example
description: An example for the google_adsense_ad_placement_api_web_example package.
publish_to: 'none'

environment:
sdk: ^3.4.0
flutter: ">=3.22.0"

dependencies:
flutter:
sdk: flutter
google_adsense_ad_placement_api_web:
path: ../
web: ^1.0.0

dev_dependencies:
build_runner: ^2.1.10
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// AdSense Ad Placement API Library
library;

export 'src/ad_placement_api_js_interop.dart'
show AdBreakDoneCallbackParamJSObject, AdBreakParamJSObject;
export 'src/enums.dart'
show BreakFormat, BreakStatus, BreakType, PreloadAdBreaks, SoundEnabled;
export 'src/globals.dart' show adPlacementApi;
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:js_interop';

import 'ad_placement_api_js_interop.dart';
import 'enums.dart';

/// Main class to interact with the Ad Placement API from Flutter Web/Dart code.
class AdPlacementApi {
/// Wraps JS Ad Placement API in a dart object.
AdPlacementApi(this._adPlacementApiJsObject);

final String _namePrefix = 'APFlutter-';

final AdPlacementApiJSObject? _adPlacementApiJsObject;

/// Key function for placing ads within your app. It defines an ad placement and takes an object called a placement config that specifies everything required to show an ad.
void adBreak({
/// The type of this placement
required BreakType type,

/// A descriptive name for this placement
String? name,

/// Prepare for the ad. Mute sounds and pause flow.
void Function()? beforeAd,

/// Resume the app flow and re-enable sound
void Function()? afterAd,

/// Show reward prompt (call showAdFn() if clicked)
void Function(JSFunction showAdFn)? beforeReward,

/// User dismissed the ad before completion
void Function()? adDismissed,

/// Ad was viewed and closed
void Function()? adViewed,

/// Always called (if provided) even if an ad didn't show
void Function(
BreakType? breakType,
String? breakName,
BreakFormat? breakFormat,
BreakStatus? breakStatus,
)? adBreakDone,
}) {
final AdBreakParamJSObject param = AdBreakParamJSObject(JSObject());
void empty() {}
void showAdDefault(JSFunction? showAd) {
if (showAd != null) {
showAd.callAsFunction();
}
}

void wrappedAdBreakDoneCallback(AdBreakDoneCallbackParamJSObject param) {
final BreakType type = BreakType.values.byName(param.breakType.toDart);
final BreakFormat format =
BreakFormat.values.byName(param.breakFormat.toDart);
final BreakStatus status =
BreakStatus.values.byName(param.breakStatus.toDart);
final String name = param.breakName.toDart;
if (adBreakDone != null) {
adBreakDone(type, name, format, status);
}
}

String breakName = _namePrefix;
if (name != null) {
breakName = breakName + name;
}

param.type = type.name.toJS;
param.name = breakName.toJS;
param.beforeAd = beforeAd != null ? beforeAd.toJS : empty.toJS;
if (type != BreakType.preroll) {
param.afterAd = afterAd != null ? afterAd.toJS : empty.toJS;
}
if (type == BreakType.reward) {
param.beforeReward =
beforeReward != null ? beforeReward.toJS : showAdDefault.toJS;
param.adDismissed = adDismissed != null ? adDismissed.toJS : empty.toJS;
param.adViewed = adViewed != null ? adViewed.toJS : empty.toJS;
}
param.adBreakDone = wrappedAdBreakDoneCallback.toJS;

_adPlacementApiJsObject?.adBreak(param);
}

/// The adConfig() call communicates the app's current configuration to the Ad Placement API.
/// The Ad Placement API can use this to tune the way it preloads ads and to filter the kinds of ads it requests so they're suitable (eg. video ads that require sound).
void adConfig(
PreloadAdBreaks preloadAdBreaks,
SoundEnabled sound,
void Function()? onReady,
) {
final AdConfigParamJSObject param = AdConfigParamJSObject(JSObject());

param.preloadAdBreaks = preloadAdBreaks.name.toJS;
param.sound = sound.name.toJS;
param.onReady = onReady?.toJS;

_adPlacementApiJsObject?.adConfig(param);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:js_interop';

/// JSInterop object that wraps the Javascript object for the Ad Placement API.
extension type AdPlacementApiJSObject(JSObject _) implements JSObject {
/// Key function for placing ads within your app. It defines an ad placement and takes an object called a placement config that specifies everything required to show an ad.
@JS()
external void adBreak(AdBreakParamJSObject o);

/// The adConfig() call communicates the app's current configuration to the Ad Placement API.
/// The Ad Placement API can use this to tune the way it preloads ads and to filter the kinds of ads it requests so they're suitable (eg. video ads that require sound).
@JS()
external void adConfig(AdConfigParamJSObject o);
}

/// JSInterop object that wraps the parameters for the adBreak call in the Ad Placement API.
extension type AdBreakParamJSObject(JSObject _) implements JSObject {
/// The type of this placement
external JSString type;

/// A descriptive name for this placement
external JSString? name;

/// Prepare for the ad. Mute sounds and pause flow.
external JSFunction? beforeAd;

/// Resume the app flow and re-enable sound
external JSFunction? afterAd;

/// Show reward prompt (call showAdFn() if clicked)
external JSFunction? beforeReward;

/// User dismissed the ad before completion
external JSFunction? adDismissed;

/// Ad was viewed and closed
external JSFunction? adViewed;

/// Always called (if provided) even if an ad didn't show
external JSFunction? adBreakDone;
}

/// JSInterop object representing the return object of the AdBreakDone callback
extension type AdBreakDoneCallbackParamJSObject(JSObject _)
implements JSObject {
/// See [BreakType] enum
external JSString breakType;

/// Name of the ad break
external JSString breakName;

/// See [BreakFormat] enum
external JSString breakFormat;

/// See [BreakStatus] enum
external JSString breakStatus;
}

/// JSInterop object that wraps the parameters for the adConfig call in the Ad Placement API.
extension type AdConfigParamJSObject(JSObject _) implements JSObject {
/// Ad preloading strategy
external JSString preloadAdBreaks;

/// This app has sound
external JSString? sound;

/// Called when API has initialised and adBreak() is ready
external JSExportedDartFunction? onReady;
}
Loading

0 comments on commit fe8cf05

Please sign in to comment.