簡易版インフィード広告よりも柔軟な表示を行いたい場合などに、カスタム型のインフィード広告機能を利用することが出来ます。
カスタムインフィード広告では自動で広告イベントを送信しないため、アプリケーション側で実装する必要があります。
通常のレイアウト同様に作成します。
レイアウト作成時に広告箇所が広告であることをユーザーが視認・理解できる文言を必ず配置して下さい。
displayedAdvertiser
を使うことで広告ごとに適切な文言を表示することが出来ます。
パラメータ名 | 説明 | 例 |
---|---|---|
title |
タイトル文言(全角20文字以内) | TestAd |
content |
説明・紹介文(全角40〜70文字以内) | テスト広告です。 |
position |
広告案件の相対位置 | 3 |
displayedAdvertiser |
表記広告主名 | 飲料会社 A社 |
creative_url |
バナー画像URL | https://example.com/image.jpg |
creative_width |
バナー画像(またはVideo)のサイズ(幅) | 640 |
creative_height |
バナー画像(またはVideo)のサイズ(高さ) | 360 |
RFPInstreamAdLoader.Builder
を使用してRFPInstreamAdLoader
のインスタンスを生成し、loadAd(Context)
を使用して広告リクエストを送信します。
RFPInstreamAdLoader adLoader = new RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID").build();
adLoader.loadAd(context); // 広告読み込み開始
val adLoader = RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID").build()
adLoader.loadAd(context) // 広告読み込み開始
取得する広告の数は引数により指定できます。
Integer[] p = {0, 3, 6};
List<Integer> positions = Arrays.asList(p);
int count = positions.size();
RFPInstreamAdLoader adLoader = new RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.count(count)
.positions(positions)
.build();
adLoader.loadAd(context); // 広告読み込み開始
val positions = mutableListOf(0, 3, 6)
val count = positions.size
val adLoader = RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.count(count)
.positions(positions)
.build()
adLoader.loadAd(context) // 広告読み込み開始
positions
はインフィード内における広告の位置を示すものとなります。
上記の例の場合、1番目、4番目、7番目の位置に広告を挿入するイメージとなります。
SDK v3.8.4からカスタムパラメータの送信に対応しました。
(カスタムパラメータの詳細は担当者にお問い合わせください)
RFPInstreamAdLoader.Builder#data()
でパラメータを指定することができます。
val loader = RFPInstreamAdLoader.Builder(spotId)
.count(count)
.positions(positions)
// 個別に設定
.data("key1", "xyzzy")
.data("key2", arrayOf("foo", "bar", "baz"))
// または Bundle で一括
// .data(bundleOf("key1" to "xyzzy", "key2" to arrayOf("foo", "bar", "baz")))
.build()
loader.loadAd(context)
取得した広告はリスナーに通知されるので、あらかじめ RFPInstreamAdLoader#onSuccess
を実装し設定しておく必要があります。
RFPInstreamAdLoader adLoader = new RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.onSuccess(new RFPInstreamAdLoader.OnSuccess() {
@Override
public void onSuccess(List<RFPInstreamInfoModel> items) {
// 広告のロード完了時
}
})
.build();
adLoader.loadAd(context); // 広告読み込み開始
val adLoader = RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.onSuccess { items ->
// 広告のロード完了時
}
.build()
adLoader.loadAd(context) // 広告読み込み開始
広告パラメータはRFPInstreamAdLoader.OnSuccess.onSuccess()
によって、RFPInstreamInfoModel
の配列として取得できます。
これをもとにビューを構築します。
RFPInstreamAdLoader adLoader = new RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.onSuccess(new RFPInstreamAdLoader.OnSuccess() {
@Override
public void onSuccess(List<RFPInstreamInfoModel> items) {
yourContentsItemList.add(0, items.get(0));
yourContentsItemList.add(3, items.get(1));
yourContentsItemList.add(6, items.get(2));
}
})
.build();
class YourAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<Object> yourContentsItemList;
/**
* @param yourContentsItemList コンテンツの元となるアイテムのリスト
*/
YourAdapter(List<Object> yourContentsItemList) {
this.yourContentsItemList = yourContentsItemList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == VIEW_TYPE_AD) { // 広告
View v = inflater.inflate(R.layout.ad_view, parent, false);
return new AdViewHolder(v);
}
View v = inflater.inflate(R.layout.content_view, parent, false);
return new ContentViewHolder(v);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Object content = yourContentsItemList.get(position);
if (content instanceof RFPInstreamInfoModel) { // 広告
RFPInstreamInfoModel adModel = (RFPInstreamInfoModel) content;
AdViewHolder adHolder = (AdViewHolder) holder;
adHolder.bindData(adModel);
return;
}
YourContent yourContent = (YourContent) content;
ContentViewHolder viewHolder = (ContentViewHolder) holder;
viewHolder.bindData(yourContent);
}
/**
* コンテンツ用ViewHolder
*/
private static class ContentViewHolder extends RecyclerView.ViewHolder {
// ... ...
}
/**
* 広告用ViewHolder
*/
private static class AdViewHolder extends RecyclerView.ViewHolder {
// ... ...
}
}
val adLoader = RFPInstreamAdLoader.Builder("YOUR_ADSPOT_ID")
.onSuccess { items ->
items?.let {
yourContentsItemList.add(0, it[0])
yourContentsItemList.add(3, it[1])
yourContentsItemList.add(6, it[2])
}
}
.build()
class YourAdapter(private yourContentsItemList: List<Any>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
if (viewType == VIEW_TYPE_AD) {
val v = inflater.inflate(R.layout.ad_view, parent, false)
return AdViewHolder(v)
}
val v = inflater.inflate(R.layout.content_view, parent, false)
return ContentViewHolder(v)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder.itemViewType == VIEW_TYPE_AD) {
val model = yourContentsItemList[position] as RFPInstreamInfoModel
val vh = holder as AdViewHolder
vh.bindData(model)
return;
}
val yourContent = yourContentsItemList[position] as YourContent
val vh = holder as ContentViewHolder
vh.bindData(yourContent)
}
private class ContentViewHolder(itemView: View)
: RecyclerView.ViewHolder(itemView) {
// ... ...
}
private class AdViewHolder(itemView: View)
: RecyclerView.ViewHolder(itemView) {
// ... ...
}
}
RFPInstreamInfoModel
の内容を元にビューを構築します。
private static class AdViewHolder extends RecyclerView.ViewHolder {
TextView advertiserName;
TextView adText;
ImageView adImage;
TextView adSponsoredLabel;
AdViewHolder(View itemView) {
super(itemView);
advertiserName = itemView.findViewById(R.id.advertiser_name);
adText = itemView.findViewById(R.id.ad_text);
adImage = itemView.findViewById(R.id.ad_image);
adSponsoredLabel = itemView.findViewById(R.id.sponsor_name);
}
void bindData(RFPInstreamInfoModel model) {
Log.d(TAG, "Ad ID is " + model.ad_id());
advertiserName.setText(model.title());
adText.setText(model.content());
adSponsoredLabel.setText(model.displayedAdvertiser());
loadImageFromUrl(adImage, model.creative_url());
}
private void loadImageFromUrl(ImageView view, String url) {
// ... ...
}
}
private class AdViewHolder(itemView: View)
: RecyclerView.ViewHolder(itemView) {
val advertiserName: TextView = itemView.findViewById(R.id.advertiser_name)
val adText: TextView = itemView.findViewById(R.id.ad_text)
val adImage: ImageView = itemView.findViewById(R.id.ad_image)
val adSponsoredLabel: TextView = itemView.findViewById(R.id.sponsor_name)
fun bindData(model: RFPInstreamInfoModel) {
advertiserName.text = model.title()
adText.text = model.content()
adSponsoredLabel.text = model.displayedAdvertiser()
loadImageFromUrl(adImage, model.creative_url())
}
fun loadImageFromUrl(view: ImageView, url: String) {
// ... ...
}
}
SDKがアニメーションGIFの再生を直接サポートしていないため、 アニメーションGIF広告を再生するには MovieまたはAnimatedImageDrawableを用いて独自に実装するか、Glideなどサードパーティ製のライブラリを利用して実装する必要があります。
カスタムインフィード広告ではイベントを自動で送信しないため、クリックおよびインプレッションの送信を実装する必要があります。
広告枠をクリックが発生した場合、RFPInstreamAdEvent#sendClickEvent()
を呼ぶ必要があります。
このメソッドはイベントの送信と同時にLPへの遷移も行うため、これだけで完結します。
private static class AdViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
RFPInstreamInfoModel adModel;
// ... ...
AdViewHolder(View itemView) {
// ... ...
itemView.setOnClickListener(this);
// ... ...
}
void bindData(RFPInstreamInfoModel model) {
adModel = model;
// ... ...
}
// ... ...
@Override
public void onClick(View view) {
// クリックイベントの送信とLPへの遷移
RFPInstreamAdEvent.sendClickEvent(view.getContext(), adModel);
}
}
private class AdViewHolder(itemView: View)
: RecyclerView.ViewHolder(itemView), View.OnClickListener {
var adModel: RFPInstreamInfoModel? = null
// ... ...
fun bindData(model: RFPInstreamInfoModel) {
adModel = model
// ... ...
}
// ... ...
override fun onClick(v: View?) {
// インプレッションの送信とLPへの遷移
RFPInstreamAdEvent.sendClickEvent(v.context, model)
}
}
広告が視認可能となった時点でRFPInstreamAdEvent#measureImp()
を呼びインプレッションを送信する必要があります。
// インプレッションを送信する
// 重複排除などは SDK が行っているため、毎回通信などは発生しない
RFPInstreamAdEvent.measureImp(context, adModel);
インプレッション送信のタイミングは広告が表示された時に行う必要がありますが、ユーザーが広告を視認可能にすることを保証するため、本SDKはアドビューアブルインプレッションを推奨します。
本SDKではこれをサポートする RFPVisibilityTracker
というクラスを提供しています。詳細については Viewable Impressionの実装 をご確認ください。