Skip to content

Commit

Permalink
Add keyword-segment lists, funnel-site lists and classifier for Brave…
Browse files Browse the repository at this point in the history
… Ads purchase intent
  • Loading branch information
Moritz Haller committed Mar 5, 2020
1 parent a1ec4e5 commit 13ae2f8
Show file tree
Hide file tree
Showing 35 changed files with 4,988 additions and 19 deletions.
3 changes: 3 additions & 0 deletions test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ test("brave_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/sorts/ads_history_sort_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/purchase_intent/funnel_sites_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/purchase_intent/keywords_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/purchase_intent/purchase_intent_classifier_unittest.cc",
]
}

Expand Down
16 changes: 16 additions & 0 deletions vendor/bat-native-ads/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ source_set("headers") {
"include/bat/ads/ads_history.h",
"include/bat/ads/bundle_state.h",
"include/bat/ads/category_content.h",
"include/bat/ads/purchase_intent_signal_history.h",
"include/bat/ads/client_info_platform_type.h",
"include/bat/ads/client_info.h",
"include/bat/ads/confirmation_type.h",
Expand Down Expand Up @@ -104,6 +105,7 @@ source_set("ads") {
"src/bat/ads/ads_history.cc",
"src/bat/ads/bundle_state.cc",
"src/bat/ads/category_content.cc",
"src/bat/ads/purchase_intent_signal_history.cc",
"src/bat/ads/client_info.cc",
"src/bat/ads/confirmation_type.cc",
"src/bat/ads/creative_ad_notification_info.cc",
Expand Down Expand Up @@ -219,6 +221,20 @@ source_set("ads") {
"src/bat/ads/internal/time.h",
"src/bat/ads/internal/uri_helper.cc",
"src/bat/ads/internal/uri_helper.h",
"src/bat/ads/internal/purchase_intent/funnel_site_info.cc",
"src/bat/ads/internal/purchase_intent/funnel_site_info.h",
"src/bat/ads/internal/purchase_intent/funnel_sites.cc",
"src/bat/ads/internal/purchase_intent/funnel_sites.h",
"src/bat/ads/internal/purchase_intent/funnel_keyword_info.cc",
"src/bat/ads/internal/purchase_intent/funnel_keyword_info.h",
"src/bat/ads/internal/purchase_intent/segment_keyword_info.cc",
"src/bat/ads/internal/purchase_intent/segment_keyword_info.h",
"src/bat/ads/internal/purchase_intent/keywords.cc",
"src/bat/ads/internal/purchase_intent/keywords.h",
"src/bat/ads/internal/purchase_intent/purchase_intent_classifier.cc",
"src/bat/ads/internal/purchase_intent/purchase_intent_classifier.h",
"src/bat/ads/internal/purchase_intent/purchase_intent_signal_info.cc",
"src/bat/ads/internal/purchase_intent/purchase_intent_signal_info.h",
]

deps = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BAT_ADS_PURCHASE_INTENT_SIGNAL_HISTORY_H_
#define BAT_ADS_PURCHASE_INTENT_SIGNAL_HISTORY_H_

#include <stdint.h>
#include <string>
#include <map>
#include <deque>

#include "bat/ads/export.h"
#include "bat/ads/result.h"

namespace ads {

struct ADS_EXPORT PurchaseIntentSignalHistory {
PurchaseIntentSignalHistory();
PurchaseIntentSignalHistory(
const PurchaseIntentSignalHistory& properties);
~PurchaseIntentSignalHistory();

bool operator==(
const PurchaseIntentSignalHistory& rhs) const;

bool operator!=(
const PurchaseIntentSignalHistory& rhs) const;

std::string ToJson() const;
Result FromJson(
const std::string& json,
std::string* error_description = nullptr);

uint64_t timestamp_in_seconds;
uint16_t weight = 0;
};

using PurchaseIntentSignalSegmentHistoryList =
std::deque<PurchaseIntentSignalHistory>;
using PurchaseIntentSignalSegmentHistoryMap =
std::map<std::string, PurchaseIntentSignalSegmentHistoryList>;

} // namespace ads

#endif // BAT_ADS_PURCHASE_INTENT_SIGNAL_HISTORY_H_
86 changes: 78 additions & 8 deletions vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "bat/ads/ads_history.h"
#include "bat/ads/confirmation_type.h"
#include "bat/ads/ad_notification_info.h"

#include "bat/ads/purchase_intent_signal_history.h"
#include "bat/ads/internal/ads_impl.h"
#include "bat/ads/internal/classification_helper.h"
#include "bat/ads/internal/locale_helper.h"
Expand All @@ -41,6 +41,8 @@
#include "bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap.h"
#include "bat/ads/internal/sorts/ads_history_sort_factory.h"
#include "bat/ads/internal/purchase_intent/purchase_intent_signal_info.h"
#include "bat/ads/internal/purchase_intent/purchase_intent_classifier.h"

#include "base/guid.h"
#include "base/rand_util.h"
Expand Down Expand Up @@ -89,6 +91,9 @@ AdsImpl::AdsImpl(AdsClient* ads_client)
ad_conversions_(std::make_unique<AdConversions>(
this, ads_client, client_.get())),
user_model_(nullptr),
purchase_intent_classifier_(std::make_unique<PurchaseIntentClassifier>(
kPurchaseIntentSignalLevel, kPurchaseIntentClassificationThreshold,
kPurchaseIntentSignalDecayTimeWindow)),
is_initialized_(false),
is_confirmations_ready_(false),
sustained_ad_notification_interaction_timer_id_(0),
Expand Down Expand Up @@ -658,6 +663,8 @@ void AdsImpl::OnPageLoaded(

CheckAdConversion(url);

ExtractPurchaseIntentSignal(url);

if (helper::Uri::MatchesDomainOrHost(url,
last_shown_ad_notification_.target_url)) {
BLOG(INFO) << "Site visited " << url
Expand Down Expand Up @@ -704,6 +711,39 @@ void AdsImpl::OnPageLoaded(
<< previous_tab_url_;
}

void AdsImpl::ExtractPurchaseIntentSignal(
const std::string& url) {
if (!ShouldClassifyPagesIfTargeted()) {
return;
}

if (!TestSearchState(url) &&
helper::Uri::MatchesDomainOrHost(url, previous_tab_url_)) {
return;
}

PurchaseIntentSignalInfo purchase_intent_signal =
purchase_intent_classifier_->ExtractIntentSignal(url);

if (purchase_intent_signal.segments.empty() &&
purchase_intent_signal.timestamp_in_seconds == 0) {
return;
}

GeneratePurchaseIntentSignalHistoryEntry(purchase_intent_signal);
BLOG(INFO) << "Purchase intent signal extracted for " << url;
}

void AdsImpl::GeneratePurchaseIntentSignalHistoryEntry(
const PurchaseIntentSignalInfo& purchase_intent_signal) {
for (const auto& segment : purchase_intent_signal.segments) {
PurchaseIntentSignalHistory history;
history.timestamp_in_seconds = purchase_intent_signal.timestamp_in_seconds;
history.weight = purchase_intent_signal.weight;
client_->AppendToPurchaseIntentSignalHistoryForSegment(segment, history);
}
}

void AdsImpl::CheckAdConversion(
const std::string& url) {
DCHECK(!url.empty());
Expand Down Expand Up @@ -838,8 +878,8 @@ std::string AdsImpl::ClassifyPage(
return winning_category;
}

std::vector<std::string> AdsImpl::GetWinningCategories() {
std::vector<std::string> winning_categories;
WinningCategoryList AdsImpl::GetWinningCategories() {
WinningCategoryList winning_categories;

if (!ShouldClassifyPagesIfTargeted()) {
return winning_categories;
Expand Down Expand Up @@ -929,6 +969,22 @@ AdsImpl::GetPageScoreCache() const {
return page_score_cache_;
}

PurchaseIntentWinningCategoryList
AdsImpl::GetWinningPurchaseIntentCategories() {
PurchaseIntentWinningCategoryList winning_categories;

PurchaseIntentSignalSegmentHistoryMap purchase_intent_signal_history =
client_->GetPurchaseIntentSignalHistory();
if (purchase_intent_signal_history.empty()) {
return winning_categories;
}

winning_categories = purchase_intent_classifier_->GetWinningCategories(
purchase_intent_signal_history, kPurchaseIntentMaxSegments);

return winning_categories;
}

void AdsImpl::TestShoppingData(
const std::string& url) {
if (!IsInitialized()) {
Expand Down Expand Up @@ -1088,12 +1144,24 @@ void AdsImpl::ServeAdNotificationIfReady(
}
}

auto categories = GetWinningCategories();
CategoryList categories = GetCategoriesToServeAd();
ServeAdNotificationFromCategories(categories);
}

CategoryList AdsImpl::GetCategoriesToServeAd() {
CategoryList categories;
WinningCategoryList contextual_categories = GetWinningCategories();
categories.insert(categories.end(),
contextual_categories.begin(), contextual_categories.end());
PurchaseIntentWinningCategoryList purchase_intent_categories =
GetWinningPurchaseIntentCategories();
categories.insert(categories.end(),
purchase_intent_categories.begin(), purchase_intent_categories.end());
return categories;
}

void AdsImpl::ServeAdNotificationFromCategories(
const std::vector<std::string>& categories) {
const CategoryList& categories) {
std::string catalog_id = bundle_->GetCatalogId();
if (catalog_id.empty()) {
FailedToServeAdNotification("No ad catalog");
Expand All @@ -1118,7 +1186,7 @@ void AdsImpl::ServeAdNotificationFromCategories(

void AdsImpl::OnServeAdNotificationFromCategories(
const Result result,
const std::vector<std::string>& categories,
const CategoryList& categories,
const CreativeAdNotificationList& ads) {
auto eligible_ads = GetEligibleAds(ads);
if (!eligible_ads.empty()) {
Expand All @@ -1132,6 +1200,8 @@ void AdsImpl::OnServeAdNotificationFromCategories(
BLOG(INFO) << " " << category;
}

// TODO(https://github.com/brave/brave-browser/issues/8486): Brave Ads
// Purchase Intent segments should not fall back to parent segments
if (ServeAdNotificationFromParentCategories(categories)) {
return;
}
Expand All @@ -1140,8 +1210,8 @@ void AdsImpl::OnServeAdNotificationFromCategories(
}

bool AdsImpl::ServeAdNotificationFromParentCategories(
const std::vector<std::string>& categories) {
std::vector<std::string> parent_categories;
const CategoryList& categories) {
CategoryList parent_categories;
for (const auto& category : categories) {
auto pos = category.find_last_of(kCategoryDelimiter);
if (pos == std::string::npos) {
Expand Down
17 changes: 15 additions & 2 deletions vendor/bat-native-ads/src/bat/ads/internal/ads_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
#include "bat/ads/internal/ad_conversions.h"
#include "bat/ads/internal/ad_notification_result_type.h"
#include "bat/ads/internal/ad_notifications.h"

#include "bat/usermodel/user_model.h"
#include "bat/ads/internal/purchase_intent/purchase_intent_classifier.h"

namespace ads {

using WinningCategoryList = std::vector<std::string>;
using CategoryList = std::vector<std::string>;

class Client;
class Bundle;
class AdsServe;
Expand All @@ -37,6 +40,8 @@ class AdConversions;
class FrequencyCapping;
class ExclusionRule;
class PermissionRule;
class PurchaseIntentClassifier;
struct PurchaseIntentSignalInfo;

class AdsImpl : public Ads {
public:
Expand Down Expand Up @@ -153,6 +158,11 @@ class AdsImpl : public Ads {
const std::string& url,
const std::string& content) override;

void ExtractPurchaseIntentSignal(
const std::string& url);
void GeneratePurchaseIntentSignalHistoryEntry(
const PurchaseIntentSignalInfo& purchase_intent_signal);

void MaybeClassifyPage(
const std::string& url,
const std::string& content);
Expand All @@ -161,7 +171,8 @@ class AdsImpl : public Ads {
const std::string& url,
const std::string& content);

std::vector<std::string> GetWinningCategories();
WinningCategoryList GetWinningCategories();
PurchaseIntentWinningCategoryList GetWinningPurchaseIntentCategories();
std::string GetWinningCategory(
const std::vector<double>& page_score);

Expand Down Expand Up @@ -208,6 +219,7 @@ class AdsImpl : public Ads {
const Result result,
const std::vector<std::string>& categories,
const CreativeAdNotificationList& ads);
CategoryList GetCategoriesToServeAd();
void ServeAdNotification(
const CreativeAdNotificationList& ads);
void OnServeAdNotification(
Expand Down Expand Up @@ -293,6 +305,7 @@ class AdsImpl : public Ads {
std::unique_ptr<FrequencyCapping> frequency_capping_;
std::unique_ptr<AdConversions> ad_conversions_;
std::unique_ptr<usermodel::UserModel> user_model_;
std::unique_ptr<PurchaseIntentClassifier> purchase_intent_classifier_;

private:
bool is_initialized_;
Expand Down
25 changes: 25 additions & 0 deletions vendor/bat-native-ads/src/bat/ads/internal/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "bat/ads/internal/client.h"

#include "bat/ads/ad_history.h"
#include "bat/ads/purchase_intent_signal_history.h"
#include "bat/ads/internal/classification_helper.h"
#include "bat/ads/internal/filtered_ad.h"
#include "bat/ads/internal/filtered_category.h"
Expand Down Expand Up @@ -80,6 +81,30 @@ std::deque<AdHistory> Client::GetAdsShownHistory() const {
return client_state_->ads_shown_history;
}

void Client::AppendToPurchaseIntentSignalHistoryForSegment(
const std::string& segment,
const PurchaseIntentSignalHistory& history) {
if (client_state_->purchase_intent_signal_history.find(segment) ==
client_state_->purchase_intent_signal_history.end()) {
client_state_->purchase_intent_signal_history.insert({segment, {}});
}

client_state_->purchase_intent_signal_history.at(
segment).push_back(history);

if (client_state_->purchase_intent_signal_history.at(segment).size() >
kMaximumEntriesPerSegmentInPurchaseIntentSignalHistory) {
client_state_->purchase_intent_signal_history.at(segment).pop_back();
}

SaveState();
}

const PurchaseIntentSignalSegmentHistoryMap&
Client::GetPurchaseIntentSignalHistory() const {
return client_state_->purchase_intent_signal_history;
}

AdContent::LikeAction Client::ToggleAdThumbUp(
const std::string& creative_instance_id,
const std::string& creative_set_id,
Expand Down
5 changes: 5 additions & 0 deletions vendor/bat-native-ads/src/bat/ads/internal/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class Client {
void AppendAdHistoryToAdsShownHistory(
const AdHistory& ad_history);
std::deque<AdHistory> GetAdsShownHistory() const;
void AppendToPurchaseIntentSignalHistoryForSegment(
const std::string& segment,
const PurchaseIntentSignalHistory& history);
const PurchaseIntentSignalSegmentHistoryMap&
GetPurchaseIntentSignalHistory() const;
AdContent::LikeAction ToggleAdThumbUp(
const std::string& creative_instance_id,
const std::string& creative_set_id,
Expand Down
Loading

0 comments on commit 13ae2f8

Please sign in to comment.