diff --git a/components/brave_ads/test/BUILD.gn b/components/brave_ads/test/BUILD.gn
index f2c47167d575..bc80cc392927 100644
--- a/components/brave_ads/test/BUILD.gn
+++ b/components/brave_ads/test/BUILD.gn
@@ -64,6 +64,7 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/ad_serving/ad_serving_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/anti_targeting/anti_targeting_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/bandits/epsilon_greedy_bandit_features_unittest.cc",
+ "//brave/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/purchase_intent/purchase_intent_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/text_classification/text_classification_features_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/features/user_activity/user_activity_features_unittest.cc",
@@ -129,6 +130,7 @@ source_set("brave_ads_unit_tests") {
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/purchase_intent/purchase_intent_resource_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/contextual/text_classification/text_classification_resource_unittest.cc",
+ "//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversions_resource_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/frequency_capping/anti_targeting_resource_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/security/conversions/conversions_util_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/security/crypto_util_unittest.cc",
diff --git a/vendor/bat-native-ads/BUILD.gn b/vendor/bat-native-ads/BUILD.gn
index c0bc101cd372..05f7153a16ca 100644
--- a/vendor/bat-native-ads/BUILD.gn
+++ b/vendor/bat-native-ads/BUILD.gn
@@ -391,6 +391,8 @@ source_set("ads") {
"src/bat/ads/internal/features/anti_targeting/anti_targeting_features.h",
"src/bat/ads/internal/features/bandits/epsilon_greedy_bandit_features.cc",
"src/bat/ads/internal/features/bandits/epsilon_greedy_bandit_features.h",
+ "src/bat/ads/internal/features/conversions/conversions_features.cc",
+ "src/bat/ads/internal/features/conversions/conversions_features.h",
"src/bat/ads/internal/features/features.cc",
"src/bat/ads/internal/features/features.h",
"src/bat/ads/internal/features/features_util.cc",
@@ -552,6 +554,10 @@ source_set("ads") {
"src/bat/ads/internal/resources/behavioral/purchase_intent/purchase_intent_resource.h",
"src/bat/ads/internal/resources/contextual/text_classification/text_classification_resource.cc",
"src/bat/ads/internal/resources/contextual/text_classification/text_classification_resource.h",
+ "src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.cc",
+ "src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.h",
+ "src/bat/ads/internal/resources/conversions/conversions_resource.cc",
+ "src/bat/ads/internal/resources/conversions/conversions_resource.h",
"src/bat/ads/internal/resources/country_components.h",
"src/bat/ads/internal/resources/frequency_capping/anti_targeting_info.cc",
"src/bat/ads/internal/resources/frequency_capping/anti_targeting_info.h",
diff --git a/vendor/bat-native-ads/data/test/resources/nnqccijfhvzwyrxpxwjrpmynaiazctqb b/vendor/bat-native-ads/data/test/resources/nnqccijfhvzwyrxpxwjrpmynaiazctqb
new file mode 100644
index 000000000000..7ac9772067b0
--- /dev/null
+++ b/vendor/bat-native-ads/data/test/resources/nnqccijfhvzwyrxpxwjrpmynaiazctqb
@@ -0,0 +1,15 @@
+{
+ "locale": "us",
+ "version": 1,
+ "timestamp": "2021-04-26 09:00:00",
+ "conversion_id_patterns": {
+ "https://brave.com/foobar": {
+ "id_pattern": "
(.*)<\/div>",
+ "search_in": "html"
+ },
+ "https://brave.com/foobar?conversion_id=*": {
+ "id_pattern": "conversion_id\\=(.*)",
+ "search_in": "url"
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc
index 12e98109db87..ca6b44bdf24a 100644
--- a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc
+++ b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc
@@ -45,6 +45,7 @@
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.h"
#include "bat/ads/internal/resources/behavioral/purchase_intent/purchase_intent_resource.h"
#include "bat/ads/internal/resources/contextual/text_classification/text_classification_resource.h"
+#include "bat/ads/internal/resources/conversions/conversions_resource.h"
#include "bat/ads/internal/resources/country_components.h"
#include "bat/ads/internal/resources/frequency_capping/anti_targeting_resource.h"
#include "bat/ads/internal/resources/language_components.h"
@@ -126,6 +127,7 @@ void AdsImpl::ChangeLocale(const std::string& locale) {
text_classification_resource_->Load();
purchase_intent_resource_->Load();
anti_targeting_resource_->Load();
+ conversions_resource_->Load();
}
void AdsImpl::OnAdsSubdivisionTargetingCodeHasChanged() {
@@ -150,7 +152,8 @@ void AdsImpl::OnHtmlLoaded(const int32_t tab_id,
const std::string original_url = redirect_chain.front();
ad_transfer_->MaybeTransferAd(tab_id, original_url);
- conversions_->MaybeConvert(redirect_chain, html);
+ conversions_->MaybeConvert(redirect_chain, html,
+ conversions_resource_->get());
}
void AdsImpl::OnTextLoaded(const int32_t tab_id,
@@ -274,6 +277,7 @@ void AdsImpl::OnResourceComponentUpdated(const std::string& id) {
} else if (kComponentCountryIds.find(id) != kComponentCountryIds.end()) {
purchase_intent_resource_->Load();
anti_targeting_resource_->Load();
+ conversions_resource_->Load();
} else {
BLOG(0, "Unknown resource for " << id);
}
@@ -424,6 +428,8 @@ void AdsImpl::set(privacy::TokenGeneratorInterface* token_generator) {
anti_targeting_resource_ = std::make_unique();
+ conversions_resource_ = std::make_unique();
+
ad_targeting_ = std::make_unique();
subdivision_targeting_ =
std::make_unique();
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.h b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.h
index 88837c896bbb..2cc14ca277a1 100644
--- a/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.h
+++ b/vendor/bat-native-ads/src/bat/ads/internal/ads_impl.h
@@ -47,6 +47,7 @@ class SubdivisionTargeting;
namespace resource {
class AntiTargeting;
+class Conversions;
class EpsilonGreedyBandit;
class PurchaseIntent;
class TextClassification;
@@ -202,6 +203,7 @@ class AdsImpl : public Ads,
std::unique_ptr
purchase_intent_processor_;
std::unique_ptr anti_targeting_resource_;
+ std::unique_ptr conversions_resource_;
std::unique_ptr
subdivision_targeting_;
std::unique_ptr ad_targeting_;
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.cc b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.cc
index 840e70a641f8..45eec294e2d5 100644
--- a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.cc
+++ b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.cc
@@ -20,6 +20,7 @@
#include "bat/ads/internal/database/tables/ad_events_database_table.h"
#include "bat/ads/internal/database/tables/conversion_queue_database_table.h"
#include "bat/ads/internal/database/tables/conversions_database_table.h"
+#include "bat/ads/internal/features/conversions/conversions_features.h"
#include "bat/ads/internal/logging.h"
#include "bat/ads/internal/time_formatting_util.h"
#include "bat/ads/internal/url_util.h"
@@ -34,8 +35,8 @@ namespace {
const int64_t kConvertAfterSeconds =
base::Time::kHoursPerDay * base::Time::kSecondsPerHour;
const int64_t kDebugConvertAfterSeconds = 10 * base::Time::kSecondsPerMinute;
-
const int64_t kExpiredConvertAfterSeconds = 1 * base::Time::kSecondsPerMinute;
+const char kSearchInUrl[] = "url";
bool HasObservationWindowForAdEventExpired(const int observation_window,
const AdEventInfo& ad_event) {
@@ -83,14 +84,41 @@ bool DoesConfirmationTypeMatchConversionType(
}
}
-std::string ExtractVerifiableConversionIdFromHtml(const std::string& html) {
- re2::StringPiece text_string_piece(html);
- RE2 r("");
+std::string ExtractConversionIdFromText(
+ const std::string& html,
+ const std::vector& redirect_chain,
+ const std::string& conversion_url_pattern,
+ const ConversionIdPatternMap& conversion_id_patterns) {
+ std::string conversion_id;
+ std::string conversion_id_pattern =
+ features::GetGetDefaultConversionIdPattern();
+ std::string text = html;
+
+ const auto iter = conversion_id_patterns.find(conversion_url_pattern);
+ if (iter != conversion_id_patterns.end()) {
+ const ConversionIdPatternInfo conversion_id_pattern_info = iter->second;
+ if (conversion_id_pattern_info.search_in == kSearchInUrl) {
+ const auto url_iter = std::find_if(
+ redirect_chain.begin(), redirect_chain.end(),
+ [=](const std::string& url) {
+ return DoesUrlMatchPattern(url, conversion_url_pattern);
+ });
+
+ if (url_iter == redirect_chain.end()) {
+ return conversion_id;
+ }
+
+ text = *url_iter;
+ }
+
+ conversion_id_pattern = conversion_id_pattern_info.id_pattern;
+ }
- std::string verifiable_conversion_id;
- RE2::FindAndConsume(&text_string_piece, r, &verifiable_conversion_id);
+ re2::StringPiece text_string_piece(text);
+ RE2 r(conversion_id_pattern);
+ RE2::FindAndConsume(&text_string_piece, r, &conversion_id);
- return verifiable_conversion_id;
+ return conversion_id;
}
std::set GetConvertedCreativeSets(const AdEventList& ad_events) {
@@ -155,8 +183,10 @@ void Conversions::RemoveObserver(ConversionsObserver* observer) {
observers_.RemoveObserver(observer);
}
-void Conversions::MaybeConvert(const std::vector& redirect_chain,
- const std::string& html) {
+void Conversions::MaybeConvert(
+ const std::vector& redirect_chain,
+ const std::string& html,
+ const ConversionIdPatternMap& conversion_id_patterns) {
if (!ShouldAllow()) {
BLOG(1, "Conversions are not allowed");
return;
@@ -168,7 +198,7 @@ void Conversions::MaybeConvert(const std::vector& redirect_chain,
return;
}
- CheckRedirectChain(redirect_chain, html);
+ CheckRedirectChain(redirect_chain, html, conversion_id_patterns);
}
void Conversions::StartTimerIfReady() {
@@ -202,7 +232,8 @@ bool Conversions::ShouldAllow() const {
void Conversions::CheckRedirectChain(
const std::vector& redirect_chain,
- const std::string& html) {
+ const std::string& html,
+ const ConversionIdPatternMap& conversion_id_patterns) {
BLOG(1, "Checking URL for conversions");
database::table::AdEvents ad_events_database_table;
@@ -254,8 +285,9 @@ void Conversions::CheckRedirectChain(
creative_set_ids.insert(ad_event.creative_set_id);
VerifiableConversionInfo verifiable_conversion;
- verifiable_conversion.id =
- ExtractVerifiableConversionIdFromHtml(html);
+ verifiable_conversion.id = ExtractConversionIdFromText(
+ html, redirect_chain, conversion.url_pattern,
+ conversion_id_patterns);
verifiable_conversion.public_key = conversion.advertiser_public_key;
Convert(ad_event, verifiable_conversion);
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.h b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.h
index 86606f8988a3..84b2d868ed90 100644
--- a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.h
+++ b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions.h
@@ -17,6 +17,7 @@
#include "bat/ads/internal/conversions/conversion_queue_item_info.h"
#include "bat/ads/internal/conversions/conversions_observer.h"
#include "bat/ads/internal/conversions/verifiable_conversion_info.h"
+#include "bat/ads/internal/resources/conversions/conversion_id_pattern_info.h"
#include "bat/ads/internal/security/conversions/verifiable_conversion_envelope_info.h"
#include "bat/ads/internal/timer.h"
@@ -34,7 +35,8 @@ class Conversions {
bool ShouldAllow() const;
void MaybeConvert(const std::vector& redirect_chain,
- const std::string& html);
+ const std::string& html,
+ const ConversionIdPatternMap& conversion_id_patterns);
void StartTimerIfReady();
@@ -44,7 +46,8 @@ class Conversions {
Timer timer_;
void CheckRedirectChain(const std::vector& redirect_chain,
- const std::string& html);
+ const std::string& html,
+ const ConversionIdPatternMap& conversion_id_patterns);
void Convert(const AdEventInfo& ad_event,
const VerifiableConversionInfo& verifiable_conversion);
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions_unittest.cc b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions_unittest.cc
index d7e5179ae9cf..607951c17610 100644
--- a/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions_unittest.cc
+++ b/vendor/bat-native-ads/src/bat/ads/internal/conversions/conversions_unittest.cc
@@ -10,7 +10,9 @@
#include "base/strings/stringprintf.h"
#include "bat/ads/internal/ad_events/ad_events.h"
#include "bat/ads/internal/database/tables/ad_events_database_table.h"
+#include "bat/ads/internal/database/tables/conversion_queue_database_table.h"
#include "bat/ads/internal/database/tables/conversions_database_table.h"
+#include "bat/ads/internal/resources/conversions/conversions_resource.h"
#include "bat/ads/internal/unittest_base.h"
#include "bat/ads/internal/unittest_util.h"
#include "bat/ads/pref_names.h"
@@ -25,6 +27,8 @@ class BatAdsConversionsTest : public UnitTestBase {
: conversions_(std::make_unique()),
ad_events_database_table_(
std::make_unique()),
+ conversion_queue_database_table_(
+ std::make_unique()),
conversions_database_table_(
std::make_unique()) {}
@@ -58,6 +62,8 @@ class BatAdsConversionsTest : public UnitTestBase {
std::unique_ptr conversions_;
std::unique_ptr ad_events_database_table_;
+ std::unique_ptr
+ conversion_queue_database_table_;
std::unique_ptr conversions_database_table_;
};
@@ -80,7 +86,7 @@ TEST_F(BatAdsConversionsTest, ShouldNotAllowConversionTracking) {
SaveConversions(conversions);
// Act
- conversions_->MaybeConvert({"https://www.foobar.com/signup"}, "");
+ conversions_->MaybeConvert({"https://www.foobar.com/signup"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -113,7 +119,7 @@ TEST_F(BatAdsConversionsTest, ConvertViewedAd) {
FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -151,7 +157,7 @@ TEST_F(BatAdsConversionsTest, ConvertClickedAd) {
FireAdEvent(conversion.creative_set_id, ConfirmationType::kClicked);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar/baz"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar/baz"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -200,9 +206,9 @@ TEST_F(BatAdsConversionsTest, ConvertMultipleAds) {
FireAdEvent(conversion_2.creative_set_id, ConfirmationType::kClicked);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/qux"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/qux"}, "", {});
- conversions_->MaybeConvert({"https://www.foo.com/bar/baz"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar/baz"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -247,7 +253,7 @@ TEST_F(BatAdsConversionsTest, ConvertViewedAdWhenAdWasDismissed) {
FireAdEvent(conversion.creative_set_id, ConfirmationType::kDismissed);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/quxbarbaz"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/quxbarbaz"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -288,7 +294,7 @@ TEST_F(BatAdsConversionsTest, DoNotConvertNonViewedOrClickedAds) {
FireAdEvent(conversion.creative_set_id, ConfirmationType::kDownvoted);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -321,7 +327,7 @@ TEST_F(BatAdsConversionsTest, DoNotConvertViewedAdForPostClick) {
FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -343,7 +349,7 @@ TEST_F(BatAdsConversionsTest, DoNotConvertAdIfConversionDoesNotExist) {
FireAdEvent(creative_set_id, ConfirmationType::kViewed);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Assert
const std::string condition =
@@ -376,10 +382,10 @@ TEST_F(BatAdsConversionsTest,
FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -399,7 +405,7 @@ TEST_F(BatAdsConversionsTest,
}
TEST_F(BatAdsConversionsTest,
- DoNotConvertAdWhenUrlDoesNotMatchConversionPattern) {
+ DoNotConvertAdWhenUrlDoesNotMatchConversionIdPattern) {
// Arrange
ConversionList conversions;
@@ -417,7 +423,7 @@ TEST_F(BatAdsConversionsTest,
FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
// Act
- conversions_->MaybeConvert({"https://www.foo.com/qux"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/qux"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -453,7 +459,7 @@ TEST_F(BatAdsConversionsTest, ConvertAdWhenTheConversionIsOnTheCuspOfExpiring) {
base::TimeDelta::FromMinutes(1));
// Act
- conversions_->MaybeConvert({"https://foo.bar.com/qux"}, "");
+ conversions_->MaybeConvert({"https://foo.bar.com/qux"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -492,7 +498,7 @@ TEST_F(BatAdsConversionsTest, DoNotConvertAdWhenTheConversionHasExpired) {
task_environment_.FastForwardBy(base::TimeDelta::FromDays(3));
// Act
- conversions_->MaybeConvert({"https://www.foo.com/bar/qux"}, "");
+ conversions_->MaybeConvert({"https://www.foo.com/bar/qux"}, "", {});
// Assert
const std::string condition = base::StringPrintf(
@@ -526,8 +532,8 @@ TEST_F(BatAdsConversionsTest, ConvertAdForRedirectChainIntermediateUrl) {
// Act
conversions_->MaybeConvert(
- {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"},
- "");
+ {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"}, "",
+ {});
// Assert
const std::string condition = base::StringPrintf(
@@ -565,8 +571,8 @@ TEST_F(BatAdsConversionsTest, ConvertAdForRedirectChainOriginalUrl) {
// Act
conversions_->MaybeConvert(
- {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"},
- "");
+ {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"}, "",
+ {});
// Assert
const std::string condition = base::StringPrintf(
@@ -604,8 +610,8 @@ TEST_F(BatAdsConversionsTest, ConvertAdForRedirectChainUrl) {
// Act
conversions_->MaybeConvert(
- {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"},
- "");
+ {"https://foo.com/bar", "https://foo.com/baz", "https://foo.com/qux"}, "",
+ {});
// Assert
const std::string condition = base::StringPrintf(
@@ -624,4 +630,141 @@ TEST_F(BatAdsConversionsTest, ConvertAdForRedirectChainUrl) {
});
}
+TEST_F(BatAdsConversionsTest, ExtractConversionId) {
+ // Arrange
+ resource::Conversions resource;
+ resource.Load();
+
+ ConversionList conversions;
+
+ ConversionInfo conversion;
+ conversion.advertiser_public_key =
+ "ofIveUY/bM7qlL9eIkAv/xbjDItFs1xRTTYKRZZsPHI=";
+ conversion.creative_set_id = "3519f52c-46a4-4c48-9c2b-c264c0067f04";
+ conversion.type = "postview";
+ conversion.url_pattern = "https://brave.com/thankyou";
+ conversion.observation_window = 3;
+ conversion.expiry_timestamp =
+ CalculateExpiryTimestamp(conversion.observation_window);
+ conversions.push_back(conversion);
+
+ SaveConversions(conversions);
+
+ FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
+
+ // Act
+ conversions_->MaybeConvert(
+ {"https://foo.bar/", "https://brave.com/thankyou"},
+ "",
+ resource.get());
+
+ // Assert
+ conversion_queue_database_table_->GetAll(
+ [=](const Result result,
+ const ConversionQueueItemList& conversion_queue_items) {
+ ASSERT_EQ(Result::SUCCESS, result);
+
+ ASSERT_EQ(1UL, conversion_queue_items.size());
+ ConversionQueueItemInfo item = conversion_queue_items.front();
+
+ ASSERT_EQ(conversion.creative_set_id, item.creative_set_id);
+ ASSERT_EQ(conversion.advertiser_public_key, item.advertiser_public_key);
+
+ const std::string expected_conversion_id = "abc123";
+ EXPECT_EQ(expected_conversion_id, item.conversion_id);
+ });
+}
+
+TEST_F(BatAdsConversionsTest, ExtractConversionIdWithResourcePatternFromHtml) {
+ // Arrange
+ resource::Conversions resource;
+ resource.Load();
+
+ ConversionList conversions;
+
+ ConversionInfo conversion;
+ conversion.advertiser_public_key =
+ "ofIveUY/bM7qlL9eIkAv/xbjDItFs1xRTTYKRZZsPHI=";
+ conversion.creative_set_id = "3519f52c-46a4-4c48-9c2b-c264c0067f04";
+ conversion.type = "postview";
+ conversion.url_pattern = "https://brave.com/foobar";
+ conversion.observation_window = 3;
+ conversion.expiry_timestamp =
+ CalculateExpiryTimestamp(conversion.observation_window);
+ conversions.push_back(conversion);
+
+ SaveConversions(conversions);
+
+ FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
+
+ // Act
+ // See associated patterns in the verifiable conversion resource
+ // /data/test/resources/nnqccijfhvzwyrxpxwjrpmynaiazctqb
+ conversions_->MaybeConvert(
+ {"https://foo.bar/", "https://brave.com/foobar"},
+ "abc123
", resource.get());
+
+ // Assert
+ conversion_queue_database_table_->GetAll(
+ [=](const Result result,
+ const ConversionQueueItemList& conversion_queue_items) {
+ ASSERT_EQ(Result::SUCCESS, result);
+
+ ASSERT_EQ(1UL, conversion_queue_items.size());
+ ConversionQueueItemInfo item = conversion_queue_items.front();
+
+ ASSERT_EQ(conversion.creative_set_id, item.creative_set_id);
+ ASSERT_EQ(conversion.advertiser_public_key, item.advertiser_public_key);
+
+ const std::string expected_conversion_id = "abc123";
+ EXPECT_EQ(expected_conversion_id, item.conversion_id);
+ });
+}
+
+TEST_F(BatAdsConversionsTest, ExtractConversionIdWithResourcePatternFromUrl) {
+ // Arrange
+ resource::Conversions resource;
+ resource.Load();
+
+ ConversionList conversions;
+
+ ConversionInfo conversion;
+ conversion.advertiser_public_key =
+ "ofIveUY/bM7qlL9eIkAv/xbjDItFs1xRTTYKRZZsPHI=";
+ conversion.creative_set_id = "3519f52c-46a4-4c48-9c2b-c264c0067f04";
+ conversion.type = "postview";
+ conversion.url_pattern = "https://brave.com/foobar?conversion_id=*";
+ conversion.observation_window = 3;
+ conversion.expiry_timestamp =
+ CalculateExpiryTimestamp(conversion.observation_window);
+ conversions.push_back(conversion);
+
+ SaveConversions(conversions);
+
+ FireAdEvent(conversion.creative_set_id, ConfirmationType::kViewed);
+
+ // Act
+ // See associated patterns in the verifiable conversion resource
+ // /data/test/resources/nnqccijfhvzwyrxpxwjrpmynaiazctqb
+ conversions_->MaybeConvert(
+ {"https://foo.bar/", "https://brave.com/foobar?conversion_id=abc123"},
+ "foobar
", resource.get());
+
+ // Assert
+ conversion_queue_database_table_->GetAll(
+ [=](const Result result,
+ const ConversionQueueItemList& conversion_queue_items) {
+ ASSERT_EQ(Result::SUCCESS, result);
+
+ ASSERT_EQ(1UL, conversion_queue_items.size());
+ ConversionQueueItemInfo item = conversion_queue_items.front();
+
+ ASSERT_EQ(conversion.creative_set_id, item.creative_set_id);
+ ASSERT_EQ(conversion.advertiser_public_key, item.advertiser_public_key);
+
+ const std::string expected_conversion_id = "abc123";
+ EXPECT_EQ(expected_conversion_id, item.conversion_id);
+ });
+}
+
} // namespace ads
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.cc b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.cc
new file mode 100644
index 000000000000..cbb2d7ec7051
--- /dev/null
+++ b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.cc
@@ -0,0 +1,46 @@
+/* Copyright (c) 2021 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/. */
+
+#include "bat/ads/internal/features/conversions/conversions_features.h"
+
+#include "bat/ads/internal/features/features_util.h"
+
+namespace ads {
+namespace features {
+
+namespace {
+
+const char kFeatureName[] = "Conversions";
+
+const char kFieldTrialParameterResourceVersion[] =
+ "conversions_resource_version";
+const int kDefaultResourceVersion = 1;
+
+const char kFieldTrialParameterDefaultConversionIdPattern[] =
+ "conversions_default_conversion_id_pattern";
+const char kDefaultDefaultConversionIdPattern[] =
+ "";
+
+} // namespace
+
+const base::Feature kFeature{kFeatureName, base::FEATURE_ENABLED_BY_DEFAULT};
+
+bool IsConversionsEnabled() {
+ return base::FeatureList::IsEnabled(kFeature);
+}
+
+int GetConversionsResourceVersion() {
+ return GetFieldTrialParamByFeatureAsInt(
+ kFeature, kFieldTrialParameterResourceVersion, kDefaultResourceVersion);
+}
+
+std::string GetGetDefaultConversionIdPattern() {
+ return GetFieldTrialParamByFeatureAsString(
+ kFeature, kFieldTrialParameterDefaultConversionIdPattern,
+ kDefaultDefaultConversionIdPattern);
+}
+
+} // namespace features
+} // namespace ads
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.h b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.h
new file mode 100644
index 000000000000..60fb6b2d1f61
--- /dev/null
+++ b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2021 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 BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_FEATURES_CONVERSIONS_CONVERSIONS_FEATURES_H_
+#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_FEATURES_CONVERSIONS_CONVERSIONS_FEATURES_H_
+
+#include
+#include
+
+#include "base/feature_list.h"
+
+namespace ads {
+namespace features {
+
+extern const base::Feature kConversions;
+
+bool IsConversionsEnabled();
+
+int GetConversionsResourceVersion();
+
+std::string GetGetDefaultConversionIdPattern();
+
+} // namespace features
+} // namespace ads
+
+#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_FEATURES_CONVERSIONS_CONVERSIONS_FEATURES_H_
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features_unittest.cc b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features_unittest.cc
new file mode 100644
index 000000000000..c6a920db920d
--- /dev/null
+++ b/vendor/bat-native-ads/src/bat/ads/internal/features/conversions/conversions_features_unittest.cc
@@ -0,0 +1,43 @@
+/* Copyright (c) 2021 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/. */
+
+#include "bat/ads/internal/features/conversions/conversions_features.h"
+
+#include "bat/ads/internal/unittest_base.h"
+
+// npm run test -- brave_unit_tests --filter=BatAds*
+
+namespace ads {
+
+TEST(BatAdsConversionsFeaturesTest, ConversionsEnabled) {
+ // Arrange
+
+ // Act
+
+ // Assert
+ EXPECT_TRUE(features::IsConversionsEnabled());
+}
+
+TEST(BatAdsConversionsFeaturesTest, ConversionsResourceVersion) {
+ // Arrange
+
+ // Act
+
+ // Assert
+ EXPECT_EQ(1, features::GetConversionsResourceVersion());
+}
+
+TEST(BatAdsConversionsFeaturesTest, DefaultConversionIdPattern) {
+ // Arrange
+
+ // Act
+
+ // Assert
+ std::string expected_pattern =
+ "";
+ EXPECT_EQ(expected_pattern, features::GetGetDefaultConversionIdPattern());
+}
+
+} // namespace ads
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.cc b/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.cc
new file mode 100644
index 000000000000..a655fc3fe205
--- /dev/null
+++ b/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.cc
@@ -0,0 +1,28 @@
+/* Copyright (c) 2021 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/. */
+
+#include "bat/ads/internal/resources/conversions/conversion_id_pattern_info.h"
+
+namespace ads {
+
+ConversionIdPatternInfo::ConversionIdPatternInfo() = default;
+
+ConversionIdPatternInfo::ConversionIdPatternInfo(
+ const ConversionIdPatternInfo& info) = default;
+
+ConversionIdPatternInfo::~ConversionIdPatternInfo() = default;
+
+bool ConversionIdPatternInfo::operator==(
+ const ConversionIdPatternInfo& rhs) const {
+ return id_pattern == rhs.id_pattern && url_pattern == rhs.url_pattern &&
+ search_in == rhs.search_in;
+}
+
+bool ConversionIdPatternInfo::operator!=(
+ const ConversionIdPatternInfo& rhs) const {
+ return !(*this == rhs);
+}
+
+} // namespace ads
diff --git a/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.h b/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.h
new file mode 100644
index 000000000000..f6f29bb10ebc
--- /dev/null
+++ b/vendor/bat-native-ads/src/bat/ads/internal/resources/conversions/conversion_id_pattern_info.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2021 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 BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_RESOURCES_CONVERSIONS_CONVERSION_ID_PATTERN_INFO_H_
+#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_RESOURCES_CONVERSIONS_CONVERSION_ID_PATTERN_INFO_H_
+
+#include