From f482e87d3f2510fcd5f2d7bacc912a8996c17841 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 22:39:28 +0200 Subject: [PATCH 01/21] Add support for NONE spending limit on Campaign.java --- .../com/taboola/backstage/model/media/campaigns/Campaign.java | 1 - .../backstage/model/media/campaigns/SpendingLimitModel.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java index 18cb829..c9bd50f 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java @@ -44,7 +44,6 @@ public class Campaign { protected PublisherBidModifier publisherBidModifier; protected BidStrategyModifiers publisherBidStrategyModifiers; protected TrafficAllocationMode trafficAllocationMode; - @Required protected Double spendingLimit; @Required protected SpendingLimitModel spendingLimitModel; diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/SpendingLimitModel.java b/src/main/java/com/taboola/backstage/model/media/campaigns/SpendingLimitModel.java index 3bc38c5..cbdaa52 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/SpendingLimitModel.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/SpendingLimitModel.java @@ -25,6 +25,7 @@ * By Taboola */ public enum SpendingLimitModel { + NONE, MONTHLY, ENTIRE, @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE From 7df3723c96072b70402b8dbcdc036562849ca19d Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:00:09 +0200 Subject: [PATCH 02/21] Adding external metadata support on campaign level --- .../model/media/campaigns/Campaign.java | 30 ++++------- .../media/campaigns/CampaignOperation.java | 6 +++ .../model/metadata/ExternalMetadata.java | 42 +++++++++++++++ .../backstage/model/metadata/KeyValue.java | 51 +++++++++++++++++++ 4 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/taboola/backstage/model/metadata/ExternalMetadata.java create mode 100644 src/main/java/com/taboola/backstage/model/metadata/KeyValue.java diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java index c9bd50f..b18173b 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java @@ -7,6 +7,7 @@ import com.taboola.backstage.model.media.campaigns.scheduling.ActivitySchedule; import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; import com.taboola.backstage.model.media.campaigns.viewability.ViewabilityTag; +import com.taboola.backstage.model.metadata.ExternalMetadata; import com.taboola.rest.api.annotations.Final; import com.taboola.rest.api.annotations.ReadOnly; import com.taboola.rest.api.annotations.Required; @@ -103,6 +104,8 @@ public class Campaign { protected CampaignsGroup campaignGroups; @ReadOnly protected CampaignType type; + protected CampaignBidStrategy bidStrategy; + protected ExternalMetadata externalMetadata; public String getId() { return id; @@ -358,35 +361,21 @@ public CampaignType getType() { return type; } + public ExternalMetadata getExternalMetadata() { + return externalMetadata; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Campaign campaign = (Campaign) o; - return Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && - Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && - Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && - spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && - Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && - Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && - Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && - Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && - Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && - Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && - Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && - Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && - Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && - Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type; + return Objects.equals(dateFormat, campaign.dateFormat) && Objects.equals(extendedDateFormat, campaign.extendedDateFormat) && Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type && bidStrategy == campaign.bidStrategy && Objects.equals(externalMetadata, campaign.externalMetadata); } @Override public int hashCode() { - return Objects.hash(id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, - trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, - platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, - audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, - marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, - cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type); + return Objects.hash(dateFormat, extendedDateFormat, id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type, bidStrategy, externalMetadata); } @Override @@ -444,6 +433,7 @@ public String toString() { ", policyReview=" + policyReview + ", campaignGroups=" + campaignGroups + ", type=" + type + + ", externalMetadata=" + externalMetadata + '}'; } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java index 671068b..15b18ad 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java @@ -5,6 +5,7 @@ import com.taboola.backstage.model.media.campaigns.brandsafety.ExternalBrandSafety; import com.taboola.backstage.model.media.campaigns.scheduling.ActivitySchedule; import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; +import com.taboola.backstage.model.metadata.ExternalMetadata; /** * Created by vladi @@ -202,4 +203,9 @@ public CampaignOperation setBrowserTargeting(CampaignTargeting browserTa this.browserTargeting = browserTargeting; return this; } + + public CampaignOperation setExternalMetadata(ExternalMetadata externalMetadata) { + this.externalMetadata = externalMetadata; + return this; + } } diff --git a/src/main/java/com/taboola/backstage/model/metadata/ExternalMetadata.java b/src/main/java/com/taboola/backstage/model/metadata/ExternalMetadata.java new file mode 100644 index 0000000..49e5564 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/metadata/ExternalMetadata.java @@ -0,0 +1,42 @@ +package com.taboola.backstage.model.metadata; + +import java.util.List; +import java.util.Objects; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 22:51 + * Copyright Taboola + */ +public class ExternalMetadata { + private List data; + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ExternalMetadata that = (ExternalMetadata) o; + return Objects.equals(data, that.data); + } + + @Override + public int hashCode() { + return Objects.hash(data); + } + + @Override + public String toString() { + return "ExternalMetadata{" + + "data=" + data + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/metadata/KeyValue.java b/src/main/java/com/taboola/backstage/model/metadata/KeyValue.java new file mode 100644 index 0000000..c447c46 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/metadata/KeyValue.java @@ -0,0 +1,51 @@ +package com.taboola.backstage.model.metadata; + +import java.util.Objects; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 22:52 + * Copyright Taboola + */ +public class KeyValue { + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + KeyValue keyValue = (KeyValue) o; + return Objects.equals(key, keyValue.key) && Objects.equals(value, keyValue.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + return "KeyValue{" + + "key='" + key + '\'' + + ", value='" + value + '\'' + + '}'; + } +} From 4ba6f230ecd958fbbe042f45dd0ea15a325a11dc Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:00:26 +0200 Subject: [PATCH 03/21] Adding more bid strategies --- .../model/media/campaigns/CampaignBidStrategy.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignBidStrategy.java b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignBidStrategy.java index 9c9838f..510dcf3 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignBidStrategy.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignBidStrategy.java @@ -1,5 +1,7 @@ package com.taboola.backstage.model.media.campaigns; +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + /** * Created by vladi.m * Date 16/04/2020 @@ -8,5 +10,8 @@ */ public enum CampaignBidStrategy { SMART, - FIXED + FIXED, + TARGET_CPA, + MAX_CONVERSIONS, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE } From e59015c57053c6719e311730ecc9f5b1624972ed Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:04:19 +0200 Subject: [PATCH 04/21] Adding learningState on Campaign.java --- .../model/media/campaigns/Campaign.java | 11 +++++++++-- .../media/campaigns/CampaignLearningState.java | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/CampaignLearningState.java diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java index b18173b..785ebbd 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java @@ -104,6 +104,8 @@ public class Campaign { protected CampaignsGroup campaignGroups; @ReadOnly protected CampaignType type; + @ReadOnly + private CampaignLearningState learningState; protected CampaignBidStrategy bidStrategy; protected ExternalMetadata externalMetadata; @@ -365,17 +367,21 @@ public ExternalMetadata getExternalMetadata() { return externalMetadata; } + public CampaignLearningState getLearningState() { + return learningState; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Campaign campaign = (Campaign) o; - return Objects.equals(dateFormat, campaign.dateFormat) && Objects.equals(extendedDateFormat, campaign.extendedDateFormat) && Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type && bidStrategy == campaign.bidStrategy && Objects.equals(externalMetadata, campaign.externalMetadata); + return Objects.equals(dateFormat, campaign.dateFormat) && Objects.equals(extendedDateFormat, campaign.extendedDateFormat) && Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type && learningState == campaign.learningState && bidStrategy == campaign.bidStrategy && Objects.equals(externalMetadata, campaign.externalMetadata); } @Override public int hashCode() { - return Objects.hash(dateFormat, extendedDateFormat, id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type, bidStrategy, externalMetadata); + return Objects.hash(dateFormat, extendedDateFormat, id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type, learningState, bidStrategy, externalMetadata); } @Override @@ -434,6 +440,7 @@ public String toString() { ", campaignGroups=" + campaignGroups + ", type=" + type + ", externalMetadata=" + externalMetadata + + ", learningState=" + learningState + '}'; } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignLearningState.java b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignLearningState.java new file mode 100644 index 0000000..6906bd9 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignLearningState.java @@ -0,0 +1,17 @@ +package com.taboola.backstage.model.media.campaigns; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 23:02 + * Copyright Taboola + */ +public enum CampaignLearningState { + EXPEDITED_LEARNING, + EMPTY_DISPLAY, + LEARNING, + LEARNING_LIMITED, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE +} From 00a70e1dcf3ab523702964e12b3f0f2d64dfd4a2 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:15:23 +0200 Subject: [PATCH 05/21] Adding learningState,appInstall,rating,logo,externalMetadata fields on CampaignItem.java --- .../media/campaigns/items/CampaignItem.java | 51 ++++++++----- .../items/CampaignItemAppInstall.java | 71 +++++++++++++++++++ .../campaigns/items/CampaignItemLogo.java | 51 +++++++++++++ .../items/CampaignItemOperation.java | 26 +++++++ .../campaigns/items/CampaignItemRating.java | 41 +++++++++++ .../items/CampaignItemsLearningState.java | 18 +++++ 6 files changed, 241 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemAppInstall.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemLogo.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemRating.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemsLearningState.java diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java index cd6171a..c3a4005 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java @@ -4,6 +4,7 @@ import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; import com.taboola.backstage.model.media.campaigns.viewability.ViewabilityTag; +import com.taboola.backstage.model.metadata.ExternalMetadata; import com.taboola.rest.api.annotations.ReadOnly; import com.taboola.rest.api.annotations.Required; @@ -37,6 +38,12 @@ public class CampaignItem { protected CampaignItemCreativeFocus creativeFocus; protected VerificationPixel verificationPixel; protected ViewabilityTag viewabilityTag; + @ReadOnly + protected CampaignItemsLearningState learningState; + protected CampaignItemAppInstall appInstall; + protected CampaignItemRating rating; + protected CampaignItemLogo logo; + protected ExternalMetadata externalMetadata; public String getId() { return id; @@ -98,6 +105,26 @@ public ViewabilityTag getViewabilityTag() { return viewabilityTag; } + public CampaignItemsLearningState getLearningState() { + return learningState; + } + + public CampaignItemAppInstall getAppInstall() { + return appInstall; + } + + public CampaignItemRating getRating() { + return rating; + } + + public CampaignItemLogo getLogo() { + return logo; + } + + public ExternalMetadata getExternalMetadata() { + return externalMetadata; + } + @Override public String toString() { return "CampaignItem{" + @@ -116,6 +143,11 @@ public String toString() { ", creativeFocus=" + creativeFocus + ", verificationPixel=" + verificationPixel + ", viewabilityTag=" + viewabilityTag + + ", learningState=" + learningState + + ", appInstall=" + appInstall + + ", rating=" + rating + + ", logo=" + logo + + ", externalMetadata=" + externalMetadata + '}'; } @@ -124,26 +156,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CampaignItem that = (CampaignItem) o; - return Objects.equals(id, that.id) && - Objects.equals(campaignId, that.campaignId) && - type == that.type && - Objects.equals(url, that.url) && - Objects.equals(thumbnailUrl, that.thumbnailUrl) && - Objects.equals(title, that.title) && - approvalState == that.approvalState && - Objects.equals(isActive, that.isActive) && - status == that.status && - Objects.equals(description, that.description) && - Objects.equals(policyReview, that.policyReview) && - Objects.equals(cta, that.cta) && - Objects.equals(creativeFocus, that.creativeFocus) && - Objects.equals(verificationPixel, that.verificationPixel) && - Objects.equals(viewabilityTag, that.viewabilityTag); + return Objects.equals(id, that.id) && Objects.equals(campaignId, that.campaignId) && type == that.type && Objects.equals(url, that.url) && Objects.equals(thumbnailUrl, that.thumbnailUrl) && Objects.equals(title, that.title) && approvalState == that.approvalState && Objects.equals(isActive, that.isActive) && status == that.status && Objects.equals(description, that.description) && Objects.equals(policyReview, that.policyReview) && Objects.equals(cta, that.cta) && Objects.equals(creativeFocus, that.creativeFocus) && Objects.equals(verificationPixel, that.verificationPixel) && Objects.equals(viewabilityTag, that.viewabilityTag) && learningState == that.learningState && Objects.equals(appInstall, that.appInstall) && Objects.equals(rating, that.rating) && Objects.equals(logo, that.logo) && Objects.equals(externalMetadata, that.externalMetadata); } @Override public int hashCode() { - return Objects.hash(id, campaignId, type, url, thumbnailUrl, title, approvalState, isActive, - status, description, policyReview, cta, creativeFocus, verificationPixel, viewabilityTag); + return Objects.hash(id, campaignId, type, url, thumbnailUrl, title, approvalState, isActive, status, description, policyReview, cta, creativeFocus, verificationPixel, viewabilityTag, learningState, appInstall, rating, logo, externalMetadata); } } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemAppInstall.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemAppInstall.java new file mode 100644 index 0000000..c08d254 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemAppInstall.java @@ -0,0 +1,71 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import java.util.Objects; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 23:05 + * Copyright Taboola + */ +public class CampaignItemAppInstall { + private String downloads; + private String appName; + private String appUrl; + private String uiVersion; + + public String getDownloads() { + return downloads; + } + + public void setDownloads(String downloads) { + this.downloads = downloads; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getAppUrl() { + return appUrl; + } + + public void setAppUrl(String appUrl) { + this.appUrl = appUrl; + } + + public String getUiVersion() { + return uiVersion; + } + + public void setUiVersion(String uiVersion) { + this.uiVersion = uiVersion; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CampaignItemAppInstall that = (CampaignItemAppInstall) o; + return Objects.equals(downloads, that.downloads) && Objects.equals(appName, that.appName) && Objects.equals(appUrl, that.appUrl) && Objects.equals(uiVersion, that.uiVersion); + } + + @Override + public int hashCode() { + return Objects.hash(downloads, appName, appUrl, uiVersion); + } + + @Override + public String toString() { + return "CampaignItemAppInstall{" + + "downloads='" + downloads + '\'' + + ", appName='" + appName + '\'' + + ", appUrl='" + appUrl + '\'' + + ", uiVersion='" + uiVersion + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemLogo.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemLogo.java new file mode 100644 index 0000000..899a41f --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemLogo.java @@ -0,0 +1,51 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import java.util.Objects; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 23:06 + * Copyright Taboola + */ +public class CampaignItemLogo { + private String logo; + private String position; + + public String getLogo() { + return logo; + } + + public void setLogo(String logo) { + this.logo = logo; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CampaignItemLogo that = (CampaignItemLogo) o; + return Objects.equals(logo, that.logo) && Objects.equals(position, that.position); + } + + @Override + public int hashCode() { + return Objects.hash(logo, position); + } + + @Override + public String toString() { + return "CampaignItemLogo{" + + "logo='" + logo + '\'' + + ", position='" + position + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java index 788c841..c74fc7a 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java @@ -2,6 +2,7 @@ import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; import com.taboola.backstage.model.media.campaigns.viewability.ViewabilityTag; +import com.taboola.backstage.model.metadata.ExternalMetadata; /** * Created by vladi @@ -61,4 +62,29 @@ public CampaignItemOperation setViewabilityTag(ViewabilityTag viewabilityTag) { this.viewabilityTag = viewabilityTag; return this; } + + public CampaignItemOperation setLearningState(CampaignItemsLearningState learningState) { + this.learningState = learningState; + return this; + } + + public CampaignItemOperation setAppInstall(CampaignItemAppInstall appInstall) { + this.appInstall = appInstall; + return this; + } + + public CampaignItemOperation setRating(CampaignItemRating rating) { + this.rating = rating; + return this; + } + + public CampaignItemOperation setLogo(CampaignItemLogo logo) { + this.logo = logo; + return this; + } + + public CampaignItemOperation setExternalMetadata(ExternalMetadata externalMetadata) { + this.externalMetadata = externalMetadata; + return this; + } } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemRating.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemRating.java new file mode 100644 index 0000000..026ab54 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemRating.java @@ -0,0 +1,41 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import java.util.Objects; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 23:06 + * Copyright Taboola + */ +public class CampaignItemRating { + private Double rating; + + public Double getRating() { + return rating; + } + + public void setRating(Double rating) { + this.rating = rating; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CampaignItemRating that = (CampaignItemRating) o; + return Objects.equals(rating, that.rating); + } + + @Override + public int hashCode() { + return Objects.hash(rating); + } + + @Override + public String toString() { + return "CampaignItemRating{" + + "rating=" + rating + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemsLearningState.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemsLearningState.java new file mode 100644 index 0000000..9293b09 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemsLearningState.java @@ -0,0 +1,18 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +/** + * Created by vladi.m + * Date 12/11/2023 + * Time 23:04 + * Copyright Taboola + */ +public enum CampaignItemsLearningState { + EMPTY_DISPLAY, + EXPEDITED_LEARNING, + LEARNING, + LEARNING_COMPLETE, + LEARNING_LIMITED, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE +} From 793c46badf7e92866299b396a23a7c4986b39111 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:15:36 +0200 Subject: [PATCH 06/21] Fixing field access level --- .../com/taboola/backstage/model/media/campaigns/Campaign.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java index 785ebbd..3f7aff7 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java @@ -105,7 +105,7 @@ public class Campaign { @ReadOnly protected CampaignType type; @ReadOnly - private CampaignLearningState learningState; + protected CampaignLearningState learningState; protected CampaignBidStrategy bidStrategy; protected ExternalMetadata externalMetadata; From 82533b06f90e6e5bcc9841549795231035cfeb4b Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:17:39 +0200 Subject: [PATCH 07/21] Adding additional CampaignItem.java status enumeration --- .../backstage/model/media/campaigns/items/ItemStatus.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/ItemStatus.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/ItemStatus.java index d1d966b..efecb7c 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/ItemStatus.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/ItemStatus.java @@ -19,5 +19,6 @@ public enum ItemStatus { STOPPED, PENDING_APPROVAL, REJECTED, + FAILED_TO_CREATE, @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE } From 1b0ed2645e4e85b1e02d6cddb88d0bbc3d7ee677 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:39:32 +0200 Subject: [PATCH 08/21] Adding read targeting whitelist on campaign level --- .../internal/BackstageCampaignsEndpoint.java | 7 +++++++ .../backstage/services/CampaignsService.java | 13 +++++++++++++ .../backstage/services/CampaignsServiceImpl.java | 7 +++++++ .../services/CampaignsServiceImplTest.java | 1 + 4 files changed, 28 insertions(+) diff --git a/src/main/java/com/taboola/backstage/internal/BackstageCampaignsEndpoint.java b/src/main/java/com/taboola/backstage/internal/BackstageCampaignsEndpoint.java index 77f4e8d..fbfa7f1 100644 --- a/src/main/java/com/taboola/backstage/internal/BackstageCampaignsEndpoint.java +++ b/src/main/java/com/taboola/backstage/internal/BackstageCampaignsEndpoint.java @@ -5,6 +5,7 @@ import com.taboola.backstage.model.media.campaigns.Campaign; import com.taboola.backstage.model.media.campaigns.CampaignBase; import com.taboola.backstage.model.media.campaigns.CampaignPatch; +import com.taboola.backstage.model.media.campaigns.CampaignTargetingCollection; import com.taboola.backstage.model.media.campaigns.CampaignsMassiveOperation; import retrofit2.http.*; @@ -77,4 +78,10 @@ CampaignPatch patchCampaign(@Header("Authorization") String accessToken, Campaign deleteCampaign(@Header("Authorization") String accessToken, @Path("account_id") String accountId, @Path("campaign_id") String campaignId); + + @GET(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "{account_id}/campaigns/{campaign_id}/targeting/publisher_targeting/whitelist") + @Headers("Content-Type: application/json") + CampaignTargetingCollection getCampaignTargetingWhiteList(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId); } diff --git a/src/main/java/com/taboola/backstage/services/CampaignsService.java b/src/main/java/com/taboola/backstage/services/CampaignsService.java index 93cc322..1f01203 100644 --- a/src/main/java/com/taboola/backstage/services/CampaignsService.java +++ b/src/main/java/com/taboola/backstage/services/CampaignsService.java @@ -9,6 +9,7 @@ import com.taboola.backstage.model.media.campaigns.CampaignBase; import com.taboola.backstage.model.media.campaigns.CampaignOperation; import com.taboola.backstage.model.media.campaigns.CampaignPatch; +import com.taboola.backstage.model.media.campaigns.CampaignTargetingCollection; import com.taboola.backstage.model.media.campaigns.CampaignsMassiveOperation; /** @@ -162,4 +163,16 @@ public interface CampaignsService { * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) */ Campaign delete(BackstageAuthentication auth, String accountId, String campaignId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Read whitelist of publisher targeting + * + * @param auth Authentication object {@link BackstageAuthentication} + * @param accountId {@link com.taboola.backstage.model.Account Account} to which {@link Campaign} belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId Account.getAccountId()} + * @return Populated {@link CampaignTargetingCollection} pojo represent collection of whitelisted Publishers + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignTargetingCollection readTargetingWhiteList(BackstageAuthentication auth, String accountId, String campaignId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; } diff --git a/src/main/java/com/taboola/backstage/services/CampaignsServiceImpl.java b/src/main/java/com/taboola/backstage/services/CampaignsServiceImpl.java index 3b9d4cb..1918d8f 100644 --- a/src/main/java/com/taboola/backstage/services/CampaignsServiceImpl.java +++ b/src/main/java/com/taboola/backstage/services/CampaignsServiceImpl.java @@ -10,6 +10,7 @@ import com.taboola.backstage.model.media.campaigns.CampaignBase; import com.taboola.backstage.model.media.campaigns.CampaignOperation; import com.taboola.backstage.model.media.campaigns.CampaignPatch; +import com.taboola.backstage.model.media.campaigns.CampaignTargetingCollection; import com.taboola.backstage.model.media.campaigns.CampaignsMassiveOperation; import com.taboola.rest.api.internal.FieldsValidator; @@ -98,4 +99,10 @@ public Campaign delete(BackstageAuthentication auth, String accountId, String ca String accessToken = auth.getToken().getAccessTokenForHeader(); return endpoint.deleteCampaign(accessToken, accountId, campaignId); } + + @Override + public CampaignTargetingCollection readTargetingWhiteList(BackstageAuthentication auth, String accountId, String campaignId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.getCampaignTargetingWhiteList(accessToken, accountId, campaignId); + } } diff --git a/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java b/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java index af4050a..44f09c3 100644 --- a/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java +++ b/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java @@ -249,4 +249,5 @@ public void testCreate_verifyStartEndData() throws NoSuchFieldException, Illegal verify(endpointMock, times(1)).createCampaign(any(), any(), any()); } + //TODO add test for readTargetingWhiteList } From 8e169f5c1a3ff48bf431fea40e4f22fa332a398b Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Sun, 12 Nov 2023 23:46:38 +0200 Subject: [PATCH 09/21] Removing travis --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b13851..cd590b5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ ## Backstage API Java Client [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.taboola/backstage-api-java-client/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/com.taboola/backstage-api-java-client) -[![Build Status](https://app.travis-ci.com/taboola/backstage-api-java-client.svg?branch=master)](https://app.travis-ci.com/taboola/backstage-api-java-client) + +[//]: # ([![Build Status](https://app.travis-ci.com/taboola/backstage-api-java-client.svg?branch=master)](https://app.travis-ci.com/taboola/backstage-api-java-client)) ### Table of Contents 1. [Getting Started](#1-getting-started) From 4c799d7e93be211c0c4b23149144e7402604daa5 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 09:18:09 +0200 Subject: [PATCH 10/21] Updating read me example for campaign and item creation --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index cd590b5..8a45a35 100644 --- a/README.md +++ b/README.md @@ -66,21 +66,21 @@ try { //create campaign Campaign campaign = backstage.campaignsService().create(clientAuth, accountId, createCampaignOperation); - //configure item - CampaignItemOperation campaignItemOperation = CampaignItemOperation.create() - .setUrl("http://www.example.com"); + //configure first item + CampaignItemOperation firstCampaignItem = CampaignItemOperation.create() + .setUrl("http://www.example.com") + .setTitle("Example Title") + .setThumbnailUrl("http://www.example.com/thumbnail.png"); - //create item - CampaignItem item = backstage.campaignItemsService().createItem(clientAuth, accountId, - campaign.getId(), campaignItemOperation); + //configure collection item creation request + CampaignItemMassiveOperation campaignItemMassiveOperation = CampaignItemMassiveOperation.create() + .addItem(firstCampaignItem); - //polling until Taboola crawler done crawling our supplied URL - while(ItemStatus.CRAWLING.equals(item.getStatus())) { - Thread.sleep(10_000L); - item = backstage.campaignItemsService().readItem(clientAuth, accountId, campaign.getId(), item.getId()); - } + //create items + Results item = backstage.campaignItemsService().createMassive(clientAuth, accountId, + campaign.getId(), campaignItemMassiveOperation); - //item done crawling, do something... + //items and campaigns were created, do something... } catch (BackstageAPIUnauthorizedException e) { logger.warn("Token is expired or bad credentials", e); @@ -94,7 +94,7 @@ try { ### 3. Authentication Supports: -1. CLIENT_CREDENTIALS +1. CLIENT_CREDENTIALS - Recommended for server to server integrations 2. PASSWORD_AUTHENTICATION Authentication service can be found under Backstage instance, see below: From 77370d9375203898dc2b011271b0367e6b339549 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 09:57:52 +0200 Subject: [PATCH 11/21] Adding conversionRules, conversionConfiguration to Campaign.java level --- .../media/campaigns/AggregationType.java | 15 +++++ .../media/campaigns/AttributionConfig.java | 48 +++++++++++++++ .../model/media/campaigns/Campaign.java | 16 ++++- .../media/campaigns/CampaignOperation.java | 10 +++ .../CampaignUnipRuleOptimizations.java | 28 +++++++++ .../campaigns/UnipRuleConfiguration.java | 61 +++++++++++++++++++ .../model/media/campaigns/UnipRuleStatus.java | 23 +++++++ 7 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/AggregationType.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/AttributionConfig.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/CampaignUnipRuleOptimizations.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleConfiguration.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleStatus.java diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/AggregationType.java b/src/main/java/com/taboola/backstage/model/media/campaigns/AggregationType.java new file mode 100644 index 0000000..375a342 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/AggregationType.java @@ -0,0 +1,15 @@ +package com.taboola.backstage.model.media.campaigns; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 9:46 + * Copyright Taboola + */ +public enum AggregationType { + AGGREGATED, + LAST_VALUE, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/AttributionConfig.java b/src/main/java/com/taboola/backstage/model/media/campaigns/AttributionConfig.java new file mode 100644 index 0000000..009c893 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/AttributionConfig.java @@ -0,0 +1,48 @@ +package com.taboola.backstage.model.media.campaigns; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 9:38 + * Copyright Taboola + */ +public class AttributionConfig { + private Integer lookBackWindowInMinutes; + private Integer vtaLookBackWindowInMinutes; + private AggregationType aggregationType; + + public Integer getLookBackWindowInMinutes() { + return lookBackWindowInMinutes; + } + + public void setLookBackWindowInMinutes(Integer lookBackWindowInMinutes) { + this.lookBackWindowInMinutes = lookBackWindowInMinutes; + } + + public Integer getVtaLookBackWindowInMinutes() { + return vtaLookBackWindowInMinutes; + } + + public void setVtaLookBackWindowInMinutes(Integer vtaLookBackWindowInMinutes) { + this.vtaLookBackWindowInMinutes = vtaLookBackWindowInMinutes; + } + + public AggregationType getAggregationType() { + return aggregationType; + } + + public void setAggregationType(AggregationType aggregationType) { + this.aggregationType = aggregationType; + } + + @Override + public String toString() { + return "AttributionConfig{" + + "lookBackWindowInMinutes=" + lookBackWindowInMinutes + + ", vtaLookBackWindowInMinutes=" + vtaLookBackWindowInMinutes + + ", aggregationType=" + aggregationType + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java index 3f7aff7..8e12410 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/Campaign.java @@ -108,6 +108,8 @@ public class Campaign { protected CampaignLearningState learningState; protected CampaignBidStrategy bidStrategy; protected ExternalMetadata externalMetadata; + protected CampaignUnipRuleOptimizations conversionRules; + protected AttributionConfig conversionConfiguration; public String getId() { return id; @@ -371,17 +373,25 @@ public CampaignLearningState getLearningState() { return learningState; } + public CampaignUnipRuleOptimizations getConversionRules() { + return conversionRules; + } + + public AttributionConfig getConversionConfiguration() { + return conversionConfiguration; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Campaign campaign = (Campaign) o; - return Objects.equals(dateFormat, campaign.dateFormat) && Objects.equals(extendedDateFormat, campaign.extendedDateFormat) && Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type && learningState == campaign.learningState && bidStrategy == campaign.bidStrategy && Objects.equals(externalMetadata, campaign.externalMetadata); + return Objects.equals(dateFormat, campaign.dateFormat) && Objects.equals(extendedDateFormat, campaign.extendedDateFormat) && Objects.equals(id, campaign.id) && Objects.equals(advertiserId, campaign.advertiserId) && Objects.equals(name, campaign.name) && Objects.equals(brandingText, campaign.brandingText) && Objects.equals(trackingCode, campaign.trackingCode) && Objects.equals(cpc, campaign.cpc) && Objects.equals(dailyCap, campaign.dailyCap) && dailyAdDeliveryModel == campaign.dailyAdDeliveryModel && Objects.equals(publisherBidModifier, campaign.publisherBidModifier) && Objects.equals(publisherBidStrategyModifiers, campaign.publisherBidStrategyModifiers) && trafficAllocationMode == campaign.trafficAllocationMode && Objects.equals(spendingLimit, campaign.spendingLimit) && spendingLimitModel == campaign.spendingLimitModel && Objects.equals(countryTargeting, campaign.countryTargeting) && Objects.equals(dmaCountryTargeting, campaign.dmaCountryTargeting) && Objects.equals(regionCountryTargeting, campaign.regionCountryTargeting) && Objects.equals(subCountryTargeting, campaign.subCountryTargeting) && Objects.equals(cityTargeting, campaign.cityTargeting) && Objects.equals(platformTargeting, campaign.platformTargeting) && Objects.equals(publisherTargeting, campaign.publisherTargeting) && Objects.equals(autoPublisherTargeting, campaign.autoPublisherTargeting) && Objects.equals(osTargeting, campaign.osTargeting) && Objects.equals(connectionTypeTargeting, campaign.connectionTypeTargeting) && Objects.equals(contextualTargeting, campaign.contextualTargeting) && Objects.equals(browserTargeting, campaign.browserTargeting) && Objects.equals(postalCodeTargeting, campaign.postalCodeTargeting) && Objects.equals(audienceSegmentsMultiTargeting, campaign.audienceSegmentsMultiTargeting) && Objects.equals(customAudienceTargeting, campaign.customAudienceTargeting) && Objects.equals(markingLabelMultiTargeting, campaign.markingLabelMultiTargeting) && Objects.equals(contextualSegmentsTargeting, campaign.contextualSegmentsTargeting) && Objects.equals(lookalikeAudienceTargeting, campaign.lookalikeAudienceTargeting) && Objects.equals(comments, campaign.comments) && bidType == campaign.bidType && marketingObjective == campaign.marketingObjective && Objects.equals(activitySchedule, campaign.activitySchedule) && Objects.equals(startDate, campaign.startDate) && Objects.equals(endDate, campaign.endDate) && Objects.equals(startDateInUtc, campaign.startDateInUtc) && Objects.equals(endDateInUtc, campaign.endDateInUtc) && Objects.equals(trafficAllocationAbTestEndDate, campaign.trafficAllocationAbTestEndDate) && approvalState == campaign.approvalState && Objects.equals(isActive, campaign.isActive) && Objects.equals(spent, campaign.spent) && status == campaign.status && Objects.equals(cpaGoal, campaign.cpaGoal) && pricingModel == campaign.pricingModel && Objects.equals(externalBrandSafety, campaign.externalBrandSafety) && Objects.equals(verificationPixel, campaign.verificationPixel) && Objects.equals(viewabilityTag, campaign.viewabilityTag) && Objects.equals(policyReview, campaign.policyReview) && Objects.equals(campaignGroups, campaign.campaignGroups) && type == campaign.type && learningState == campaign.learningState && bidStrategy == campaign.bidStrategy && Objects.equals(externalMetadata, campaign.externalMetadata) && Objects.equals(conversionRules, campaign.conversionRules) && Objects.equals(conversionConfiguration, campaign.conversionConfiguration); } @Override public int hashCode() { - return Objects.hash(dateFormat, extendedDateFormat, id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type, learningState, bidStrategy, externalMetadata); + return Objects.hash(dateFormat, extendedDateFormat, id, advertiserId, name, brandingText, trackingCode, cpc, dailyCap, dailyAdDeliveryModel, publisherBidModifier, publisherBidStrategyModifiers, trafficAllocationMode, spendingLimit, spendingLimitModel, countryTargeting, dmaCountryTargeting, regionCountryTargeting, subCountryTargeting, cityTargeting, platformTargeting, publisherTargeting, autoPublisherTargeting, osTargeting, connectionTypeTargeting, contextualTargeting, browserTargeting, postalCodeTargeting, audienceSegmentsMultiTargeting, customAudienceTargeting, markingLabelMultiTargeting, contextualSegmentsTargeting, lookalikeAudienceTargeting, comments, bidType, marketingObjective, activitySchedule, startDate, endDate, startDateInUtc, endDateInUtc, trafficAllocationAbTestEndDate, approvalState, isActive, spent, status, cpaGoal, pricingModel, externalBrandSafety, verificationPixel, viewabilityTag, policyReview, campaignGroups, type, learningState, bidStrategy, externalMetadata, conversionRules, conversionConfiguration); } @Override @@ -441,6 +451,8 @@ public String toString() { ", type=" + type + ", externalMetadata=" + externalMetadata + ", learningState=" + learningState + + ", conversionRules=" + conversionRules + + ", conversionConfiguration=" + conversionConfiguration + '}'; } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java index 15b18ad..fc91c48 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignOperation.java @@ -208,4 +208,14 @@ public CampaignOperation setExternalMetadata(ExternalMetadata externalMetadata) this.externalMetadata = externalMetadata; return this; } + + public CampaignOperation setConversionRules(CampaignUnipRuleOptimizations conversionRules) { + this.conversionRules = conversionRules; + return this; + } + + public CampaignOperation setConversionConfiguration(AttributionConfig conversionConfiguration) { + this.conversionConfiguration = conversionConfiguration; + return this; + } } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignUnipRuleOptimizations.java b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignUnipRuleOptimizations.java new file mode 100644 index 0000000..ca5d0ac --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/CampaignUnipRuleOptimizations.java @@ -0,0 +1,28 @@ +package com.taboola.backstage.model.media.campaigns; + +import java.util.List; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 9:38 + * Copyright Taboola + */ +public class CampaignUnipRuleOptimizations { + private List rules; + + public List getRules() { + return rules; + } + + public void setRules(List rules) { + this.rules = rules; + } + + @Override + public String toString() { + return "CampaignUnipRuleOptimizations{" + + "rules=" + rules + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleConfiguration.java b/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleConfiguration.java new file mode 100644 index 0000000..d7dfbed --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleConfiguration.java @@ -0,0 +1,61 @@ +package com.taboola.backstage.model.media.campaigns; + +import com.taboola.rest.api.annotations.ReadOnly; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 9:38 + * Copyright Taboola + */ +public class UnipRuleConfiguration { + private Long id; + @ReadOnly + private String displayName; + @ReadOnly + private UnipRuleStatus status; + @ReadOnly + private Boolean includeInTotalConversions; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public UnipRuleStatus getStatus() { + return status; + } + + public void setStatus(UnipRuleStatus status) { + this.status = status; + } + + public Boolean getIncludeInTotalConversions() { + return includeInTotalConversions; + } + + public void setIncludeInTotalConversions(Boolean includeInTotalConversions) { + this.includeInTotalConversions = includeInTotalConversions; + } + + @Override + public String toString() { + return "UnipRuleConfiguration{" + + "id=" + id + + ", displayName='" + displayName + '\'' + + ", status=" + status + + ", includeInTotalConversions=" + includeInTotalConversions + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleStatus.java b/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleStatus.java new file mode 100644 index 0000000..87c77a9 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/UnipRuleStatus.java @@ -0,0 +1,23 @@ +package com.taboola.backstage.model.media.campaigns; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 9:39 + * Copyright Taboola + */ +public enum UnipRuleStatus { + ACTIVE, + NO_RECENT_ACTIVITY, + NO_ACTIVITY_YET, + READY, + PROCESSING, + DISABLED, + ARCHIVED, + ERROR, + GAINING_SCALE, + ERROR_SEED_SIZE_TOO_SMALL, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE +} From 181a691ca846164840a39b964b915b3982d6e2d2 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 15:06:35 +0200 Subject: [PATCH 12/21] Adding unit test for readTargetingWhiteList on Campaign level --- .../services/CampaignsServiceImplTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java b/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java index 44f09c3..10e6ce7 100644 --- a/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java +++ b/src/test/java/com/taboola/backstage/services/CampaignsServiceImplTest.java @@ -7,11 +7,13 @@ import com.taboola.backstage.model.media.campaigns.CampaignBase; import com.taboola.backstage.model.media.campaigns.CampaignOperation; import com.taboola.backstage.model.media.campaigns.CampaignPatch; +import com.taboola.backstage.model.media.campaigns.CampaignTargetingCollection; import com.taboola.backstage.model.media.campaigns.CampaignsMassiveOperation; import com.taboola.backstage.model.media.campaigns.SpendingLimitModel; import org.junit.Before; import org.junit.Test; import com.taboola.backstage.BackstageTestBase; +import com.taboola.backstage.model.media.campaigns.targeting.Type; import java.lang.reflect.Field; import java.text.ParseException; @@ -249,5 +251,14 @@ public void testCreate_verifyStartEndData() throws NoSuchFieldException, Illegal verify(endpointMock, times(1)).createCampaign(any(), any(), any()); } - //TODO add test for readTargetingWhiteList + @Test + public void testReadTargetingWhiteList() { + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + CampaignTargetingCollection results = new CampaignTargetingCollection<>(Collections.singleton("987654123"), Type.INCLUDE); + when(endpointMock.getCampaignTargetingWhiteList(auth.getToken().getAccessTokenForHeader(),"accountId", "123")).thenReturn(results); + + CampaignTargetingCollection actual = testInstance.readTargetingWhiteList(auth, "accountId", "123"); + assertEquals("Invalid campaign results", results, actual); + verify(endpointMock, times(1)).getCampaignTargetingWhiteList(any(), any(), any()); + } } From cd8ec9f651f71451026273b4d12c202b6f5e6b2d Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 21:21:00 +0200 Subject: [PATCH 13/21] Adding disclaimer url to CampaignItem.java --- .../media/campaigns/items/CampaignItem.java | 10 +++++-- .../items/CampaignItemDisclaimer.java | 26 +++++++++++++++++++ .../items/CampaignItemOperation.java | 5 ++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemDisclaimer.java diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java index c3a4005..361a28d 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItem.java @@ -43,6 +43,7 @@ public class CampaignItem { protected CampaignItemAppInstall appInstall; protected CampaignItemRating rating; protected CampaignItemLogo logo; + protected CampaignItemDisclaimer disclaimer; protected ExternalMetadata externalMetadata; public String getId() { @@ -125,6 +126,10 @@ public ExternalMetadata getExternalMetadata() { return externalMetadata; } + public CampaignItemDisclaimer getDisclaimer() { + return disclaimer; + } + @Override public String toString() { return "CampaignItem{" + @@ -147,6 +152,7 @@ public String toString() { ", appInstall=" + appInstall + ", rating=" + rating + ", logo=" + logo + + ", disclaimer=" + disclaimer + ", externalMetadata=" + externalMetadata + '}'; } @@ -156,11 +162,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CampaignItem that = (CampaignItem) o; - return Objects.equals(id, that.id) && Objects.equals(campaignId, that.campaignId) && type == that.type && Objects.equals(url, that.url) && Objects.equals(thumbnailUrl, that.thumbnailUrl) && Objects.equals(title, that.title) && approvalState == that.approvalState && Objects.equals(isActive, that.isActive) && status == that.status && Objects.equals(description, that.description) && Objects.equals(policyReview, that.policyReview) && Objects.equals(cta, that.cta) && Objects.equals(creativeFocus, that.creativeFocus) && Objects.equals(verificationPixel, that.verificationPixel) && Objects.equals(viewabilityTag, that.viewabilityTag) && learningState == that.learningState && Objects.equals(appInstall, that.appInstall) && Objects.equals(rating, that.rating) && Objects.equals(logo, that.logo) && Objects.equals(externalMetadata, that.externalMetadata); + return Objects.equals(id, that.id) && Objects.equals(campaignId, that.campaignId) && type == that.type && Objects.equals(url, that.url) && Objects.equals(thumbnailUrl, that.thumbnailUrl) && Objects.equals(title, that.title) && approvalState == that.approvalState && Objects.equals(isActive, that.isActive) && status == that.status && Objects.equals(description, that.description) && Objects.equals(policyReview, that.policyReview) && Objects.equals(cta, that.cta) && Objects.equals(creativeFocus, that.creativeFocus) && Objects.equals(verificationPixel, that.verificationPixel) && Objects.equals(viewabilityTag, that.viewabilityTag) && learningState == that.learningState && Objects.equals(appInstall, that.appInstall) && Objects.equals(rating, that.rating) && Objects.equals(logo, that.logo) && Objects.equals(disclaimer, that.disclaimer) && Objects.equals(externalMetadata, that.externalMetadata); } @Override public int hashCode() { - return Objects.hash(id, campaignId, type, url, thumbnailUrl, title, approvalState, isActive, status, description, policyReview, cta, creativeFocus, verificationPixel, viewabilityTag, learningState, appInstall, rating, logo, externalMetadata); + return Objects.hash(id, campaignId, type, url, thumbnailUrl, title, approvalState, isActive, status, description, policyReview, cta, creativeFocus, verificationPixel, viewabilityTag, learningState, appInstall, rating, logo, disclaimer, externalMetadata); } } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemDisclaimer.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemDisclaimer.java new file mode 100644 index 0000000..d43821c --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemDisclaimer.java @@ -0,0 +1,26 @@ +package com.taboola.backstage.model.media.campaigns.items; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:11 + * Copyright Taboola + */ +public class CampaignItemDisclaimer { + private String disclaimerUrl; + + public String getDisclaimerUrl() { + return disclaimerUrl; + } + + public void setDisclaimerUrl(String disclaimerUrl) { + this.disclaimerUrl = disclaimerUrl; + } + + @Override + public String toString() { + return "CampaignItemDisclaimer{" + + "disclaimerUrl='" + disclaimerUrl + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java index c74fc7a..c015e8f 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java @@ -83,6 +83,11 @@ public CampaignItemOperation setLogo(CampaignItemLogo logo) { return this; } + public CampaignItemOperation setDisclaimer(CampaignItemDisclaimer disclaimer) { + this.disclaimer = disclaimer; + return this; + } + public CampaignItemOperation setExternalMetadata(ExternalMetadata externalMetadata) { this.externalMetadata = externalMetadata; return this; From fb49f30519868f03be84cd65fee5935228c11c97 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 22:20:29 +0200 Subject: [PATCH 14/21] Adding performance video endpoints and models --- .../BackstageCampaignItemsEndpoint.java | 52 ++++++ .../items/CampaignPerformanceVideoItem.java | 161 ++++++++++++++++++ ...CampaignPerformanceVideoItemOperation.java | 109 ++++++++++++ .../campaigns/items/MediaUploadSource.java | 21 +++ .../campaigns/items/MotionAdsStudio.java | 36 ++++ .../PerformanceVideoBulkCreateOperation.java | 48 ++++++ .../PerformanceVideoBulkUpdateOperation.java | 48 ++++++ .../services/CampaignItemsService.java | 130 ++++++++++++++ .../services/CampaignItemsServiceImpl.java | 82 +++++++++ 9 files changed, 687 insertions(+) create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/MediaUploadSource.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/MotionAdsStudio.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkCreateOperation.java create mode 100644 src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkUpdateOperation.java diff --git a/src/main/java/com/taboola/backstage/internal/BackstageCampaignItemsEndpoint.java b/src/main/java/com/taboola/backstage/internal/BackstageCampaignItemsEndpoint.java index bdcea3b..db56e4c 100644 --- a/src/main/java/com/taboola/backstage/internal/BackstageCampaignItemsEndpoint.java +++ b/src/main/java/com/taboola/backstage/internal/BackstageCampaignItemsEndpoint.java @@ -7,6 +7,9 @@ import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveCreationOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveUpdateOperation; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItem; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkCreateOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkUpdateOperation; import retrofit2.http.*; @@ -103,4 +106,53 @@ CampaignItem deleteItem(@Header("Authorization") String accessToken, @Path("account_id") String accountId, @Path("campaign_id") String campaignId, @Path("item_id") String itemId) throws BackstageAPIException; + + @GET(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/campaigns/{campaign_id}/performance-video/items") + @Headers("Content-Type: application/json") + Results getVideoCreatives(@Header("Authorization") String authToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId) throws BackstageAPIException; + + @GET(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/campaigns/{campaign_id}/performance-video/items/{creative_id}") + @Headers("Content-Type: application/json") + CampaignPerformanceVideoItem getVideoCreative(@Header("Authorization") String authToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId, + @Path("creative_id") String creativeId) throws BackstageAPIException; + + @POST(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/campaigns/{campaign_id}/performance-video/items") + @Headers("Content-Type: application/json") + CampaignPerformanceVideoItem insertVideoCreative(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId, + @Body CampaignPerformanceVideoItem newItem) throws BackstageAPIException; + + @PUT(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/campaigns/{campaign_id}/performance-video/items/{creative_id}") + @Headers("Content-Type: application/json") + CampaignPerformanceVideoItem updateVideoCreative(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId, + @Path("creative_id") String creativeId, + @Query("bypass_url_response_validation") boolean bypassUrlResponseValidation, + @Body CampaignPerformanceVideoItem updatePojo) throws BackstageAPIException; + + @DELETE(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/campaigns/{campaign_id}/performance-video/items/{creative_id}") + @Headers("Content-Type: application/json") + CampaignPerformanceVideoItem deleteVideoCreative(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Path("campaign_id") String campaignId, + @Path("creative_id") String creativeId) throws BackstageAPIException; + + @PUT(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/items/bulk/performance-video") + @Headers("Content-Type: application/json") + Results bulkCreateVideo(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Body PerformanceVideoBulkCreateOperation create) throws BackstageAPIException; + + @POST(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/items/bulk/performance-video") + @Headers("Content-Type: application/json") + Results bulkUpdateVideo(@Header("Authorization") String accessToken, + @Path("account_id") String accountId, + @Query("bypass_url_response_validation") boolean bypassUrlResponseValidation, + @Body PerformanceVideoBulkUpdateOperation update) throws BackstageAPIException; } diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java new file mode 100644 index 0000000..32fbdb5 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java @@ -0,0 +1,161 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; +import com.taboola.backstage.model.media.campaigns.viewability.ViewabilityTag; +import com.taboola.rest.api.annotations.ReadOnly; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:07 + * Copyright Taboola + */ +public class CampaignPerformanceVideoItem { + @ReadOnly + protected String id; + protected String campaignId; + protected String url; + protected String title; + protected String description; + protected ItemApprovalState approvalState; + protected Boolean isActive; + @ReadOnly + protected ItemStatus status; + @ReadOnly + protected CampaignItemPolicyReview policyReview; + protected String fallbackUrl; + protected String gifUrl; + protected String videoUrl; + protected CampaignItemCTA cta; + protected String recommendedFBImage; + protected VerificationPixel verificationPixel; + protected ViewabilityTag viewabilityTag; + protected MediaUploadSource mediaUploadSource; + protected MotionAdsStudio motionAdsStudio; + protected CampaignItemAppInstall appInstall; + protected CampaignItemRating rating; + protected CampaignItemLogo logo; + protected CampaignItemDisclaimer disclaimer; + protected String brandingText; + + public String getId() { + return id; + } + + public String getCampaignId() { + return campaignId; + } + + public String getUrl() { + return url; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public ItemApprovalState getApprovalState() { + return approvalState; + } + + public Boolean getIsActive() { + return isActive; + } + + public ItemStatus getStatus() { + return status; + } + + public CampaignItemPolicyReview getPolicyReview() { + return policyReview; + } + + public String getFallbackUrl() { + return fallbackUrl; + } + + public String getGifUrl() { + return gifUrl; + } + + public String getVideoUrl() { + return videoUrl; + } + + public CampaignItemCTA getCta() { + return cta; + } + + public String getRecommendedFBImage() { + return recommendedFBImage; + } + + public VerificationPixel getVerificationPixel() { + return verificationPixel; + } + + public ViewabilityTag getViewabilityTag() { + return viewabilityTag; + } + + public MediaUploadSource getMediaUploadSource() { + return mediaUploadSource; + } + + public MotionAdsStudio getMotionAdsStudio() { + return motionAdsStudio; + } + + public CampaignItemAppInstall getAppInstall() { + return appInstall; + } + + public CampaignItemRating getRating() { + return rating; + } + + public CampaignItemLogo getLogo() { + return logo; + } + + public CampaignItemDisclaimer getDisclaimer() { + return disclaimer; + } + + public String getBrandingText() { + return brandingText; + } + + @Override + public String toString() { + return "CampaignPerformanceVideoItem{" + + "id='" + id + '\'' + + ", campaignId='" + campaignId + '\'' + + ", url='" + url + '\'' + + ", title='" + title + '\'' + + ", description='" + description + '\'' + + ", approvalState=" + approvalState + + ", isActive=" + isActive + + ", status=" + status + + ", policyReview=" + policyReview + + ", fallbackUrl='" + fallbackUrl + '\'' + + ", gifUrl='" + gifUrl + '\'' + + ", videoUrl='" + videoUrl + '\'' + + ", cta=" + cta + + ", recommendedFBImage='" + recommendedFBImage + '\'' + + ", verificationPixel=" + verificationPixel + + ", viewabilityTag=" + viewabilityTag + + ", mediaUploadSource=" + mediaUploadSource + + ", motionAdsStudio=" + motionAdsStudio + + ", appInstall=" + appInstall + + ", rating=" + rating + + ", logo=" + logo + + ", disclaimer=" + disclaimer + + ", brandingText='" + brandingText + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java new file mode 100644 index 0000000..9ed7940 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java @@ -0,0 +1,109 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import com.taboola.backstage.model.media.campaigns.verifications.VerificationPixel; +import com.taboola.backstage.model.media.campaigns.viewability.ViewabilityTag; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:16 + * Copyright Taboola + */ +public class CampaignPerformanceVideoItemOperation extends CampaignPerformanceVideoItem { + + private CampaignPerformanceVideoItemOperation() { } + + public static CampaignPerformanceVideoItemOperation create() { + return new CampaignPerformanceVideoItemOperation(); + } + + public CampaignPerformanceVideoItemOperation setCampaignId(String campaignId) { + this.campaignId = campaignId; + return this; + } + + public CampaignPerformanceVideoItemOperation setUrl(String url) { + this.url = url; + return this; + } + + public CampaignPerformanceVideoItemOperation setTitle(String title) { + this.title = title; + return this; + } + + public CampaignPerformanceVideoItemOperation setDescription(String description) { + this.description = description; + return this; + } + + public CampaignPerformanceVideoItemOperation setApprovalState(ItemApprovalState approvalState) { + this.approvalState = approvalState; + return this; + } + + public CampaignPerformanceVideoItemOperation setActive(Boolean active) { + isActive = active; + return this; + } + + public CampaignPerformanceVideoItemOperation setFallbackUrl(String fallbackUrl) { + this.fallbackUrl = fallbackUrl; + return this; + } + + public CampaignPerformanceVideoItemOperation setGifUrl(String gifUrl) { + this.gifUrl = gifUrl; + return this; + } + + public CampaignPerformanceVideoItemOperation setVideoUrl(String videoUrl) { + this.videoUrl = videoUrl; + return this; + } + + public CampaignPerformanceVideoItemOperation setCta(CampaignItemCTA cta) { + this.cta = cta; + return this; + } + + public CampaignPerformanceVideoItemOperation setVerificationPixel(VerificationPixel verificationPixel) { + this.verificationPixel = verificationPixel; + return this; + } + + public CampaignPerformanceVideoItemOperation setViewabilityTag(ViewabilityTag viewabilityTag) { + this.viewabilityTag = viewabilityTag; + return this; + } + + public CampaignPerformanceVideoItemOperation setMotionAdsStudio(MotionAdsStudio motionAdsStudio) { + this.motionAdsStudio = motionAdsStudio; + return this; + } + + public CampaignPerformanceVideoItemOperation setAppInstall(CampaignItemAppInstall appInstall) { + this.appInstall = appInstall; + return this; + } + + public CampaignPerformanceVideoItemOperation setRating(CampaignItemRating rating) { + this.rating = rating; + return this; + } + + public CampaignPerformanceVideoItemOperation setLogo(CampaignItemLogo logo) { + this.logo = logo; + return this; + } + + public CampaignPerformanceVideoItemOperation setDisclaimer(CampaignItemDisclaimer disclaimer) { + this.disclaimer = disclaimer; + return this; + } + + public CampaignPerformanceVideoItemOperation setBrandingText(String brandingText) { + this.brandingText = brandingText; + return this; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/MediaUploadSource.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/MediaUploadSource.java new file mode 100644 index 0000000..193fa9c --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/MediaUploadSource.java @@ -0,0 +1,21 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:14 + * Copyright Taboola + */ +public enum MediaUploadSource { + WOCHIT, + URL, + URL_TA, + URL_OFFSTAGE, + FILE, + MEDIA_LIBRARY, + RECOMMENDED_MEDIA, + URL_BULK_UPLOAD, + @JsonEnumDefaultValue UNSUPPORTED_BY_SDK_VALUE +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/MotionAdsStudio.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/MotionAdsStudio.java new file mode 100644 index 0000000..55defe5 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/MotionAdsStudio.java @@ -0,0 +1,36 @@ +package com.taboola.backstage.model.media.campaigns.items; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:15 + * Copyright Taboola + */ +public class MotionAdsStudio { + private String vendorTemplateType; + private String vendorVideoId; + + public String getVendorTemplateType() { + return vendorTemplateType; + } + + public void setVendorTemplateType(String vendorTemplateType) { + this.vendorTemplateType = vendorTemplateType; + } + + public String getVendorVideoId() { + return vendorVideoId; + } + + public void setVendorVideoId(String vendorVideoId) { + this.vendorVideoId = vendorVideoId; + } + + @Override + public String toString() { + return "MotionAdsStudio{" + + "vendorTemplateType='" + vendorTemplateType + '\'' + + ", vendorVideoId='" + vendorVideoId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkCreateOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkCreateOperation.java new file mode 100644 index 0000000..35e459a --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkCreateOperation.java @@ -0,0 +1,48 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import java.util.List; + +import com.taboola.rest.api.annotations.Required; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:23 + * Copyright Taboola + */ +public class PerformanceVideoBulkCreateOperation { + @Required + private List campaignIds; + @Required + private List items; + + public static PerformanceVideoBulkCreateOperation create() { + return new PerformanceVideoBulkCreateOperation(); + } + + public List getCampaignIds() { + return campaignIds; + } + + public PerformanceVideoBulkCreateOperation setCampaignIds(List campaignIds) { + this.campaignIds = campaignIds; + return this; + } + + public List getItems() { + return items; + } + + public PerformanceVideoBulkCreateOperation setItems(List items) { + this.items = items; + return this; + } + + @Override + public String toString() { + return "PerformanceVideoBulkCreateOperation{" + + "campaignIds=" + campaignIds + + ", items=" + items + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkUpdateOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkUpdateOperation.java new file mode 100644 index 0000000..680dcf6 --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/PerformanceVideoBulkUpdateOperation.java @@ -0,0 +1,48 @@ +package com.taboola.backstage.model.media.campaigns.items; + +import java.util.List; + +import com.taboola.rest.api.annotations.Required; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 21:26 + * Copyright Taboola + */ +public class PerformanceVideoBulkUpdateOperation { + @Required + private List itemsToUpdate; + @Required + private CampaignPerformanceVideoItem baselineItem; + + public static PerformanceVideoBulkUpdateOperation create() { + return new PerformanceVideoBulkUpdateOperation(); + } + + public List getItemsToUpdate() { + return itemsToUpdate; + } + + public PerformanceVideoBulkUpdateOperation setItemsToUpdate(List itemsToUpdate) { + this.itemsToUpdate = itemsToUpdate; + return this; + } + + public CampaignPerformanceVideoItem getBaselineItem() { + return baselineItem; + } + + public PerformanceVideoBulkUpdateOperation setBaselineItem(CampaignPerformanceVideoItem baselineItem) { + this.baselineItem = baselineItem; + return this; + } + + @Override + public String toString() { + return "PerformanceVideoBulkUpdateOperation{" + + "itemsToUpdate=" + itemsToUpdate + + ", baselineItem=" + baselineItem + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/services/CampaignItemsService.java b/src/main/java/com/taboola/backstage/services/CampaignItemsService.java index bb89239..81c18b0 100644 --- a/src/main/java/com/taboola/backstage/services/CampaignItemsService.java +++ b/src/main/java/com/taboola/backstage/services/CampaignItemsService.java @@ -10,6 +10,10 @@ import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveUpdateOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemOperation; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItem; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItemOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkCreateOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkUpdateOperation; /** * {@link CampaignItem} entity CRUD operations @@ -263,4 +267,130 @@ public interface CampaignItemsService { * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) */ CampaignItem deleteItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Fetch all {@link CampaignPerformanceVideoItem} associated with a specific {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @return Fully populated collection of {@link CampaignPerformanceVideoItem} pojos + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + Results readPerformanceVideoItems(BackstageAuthentication auth, String accountId, String campaignId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Fetch specific by id {@link CampaignPerformanceVideoItem} associated with a specific {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @param itemId {@link CampaignPerformanceVideoItem} Id to read. Taken from {@link CampaignPerformanceVideoItem#getId()} object + * @return {@link CampaignPerformanceVideoItem} , Taken from {@link CampaignPerformanceVideoItem#getId()} object + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignPerformanceVideoItem readPerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Create {@link CampaignPerformanceVideoItem} under given {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @param item {@link CampaignPerformanceVideoItemOperation} + * @return Created {@link CampaignPerformanceVideoItem} pojo + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignPerformanceVideoItem createPerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, CampaignPerformanceVideoItemOperation item) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Update {@link CampaignPerformanceVideoItem} under given {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @param itemId {@link CampaignPerformanceVideoItem} , Taken from {@link CampaignPerformanceVideoItem#getId()} object + * @param item {@link CampaignPerformanceVideoItemOperation} + * @return Updated {@link CampaignPerformanceVideoItem} pojo + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignPerformanceVideoItem updatePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId, CampaignPerformanceVideoItemOperation item) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Update {@link CampaignPerformanceVideoItem} under given {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @param itemId {@link CampaignPerformanceVideoItem} , Taken from {@link CampaignPerformanceVideoItem#getId()} object + * @param item {@link CampaignPerformanceVideoItemOperation} + * @param bypassUrlResponseValidation Avoid URL validation + * @return Updated {@link CampaignPerformanceVideoItem} pojo + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignPerformanceVideoItem updatePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId, CampaignPerformanceVideoItemOperation item, boolean bypassUrlResponseValidation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Delete {@link CampaignPerformanceVideoItem} under given {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param campaignId Under what {@link com.taboola.backstage.model.media.campaigns.Campaign Campaign} the new {@link CampaignItem} is going to be create. Taken from {@link com.taboola.backstage.model.media.campaigns.Campaign#getId Campaign#getId()} object + * @param itemId {@link CampaignPerformanceVideoItem} , Taken from {@link CampaignPerformanceVideoItem#getId()} object + * @return Deleted {@link CampaignPerformanceVideoItem} pojo + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + CampaignPerformanceVideoItem deletePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Bulk create {@link CampaignPerformanceVideoItem} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param bulkCreateOperation {@link PerformanceVideoBulkCreateOperation} + * @return Fully populated collection of {@link CampaignPerformanceVideoItem} pojos + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + Results bulkCreatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkCreateOperation bulkCreateOperation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Bulk Update {@link CampaignPerformanceVideoItem} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param bulkUpdateOperation {@link PerformanceVideoBulkUpdateOperation} + * @return Fully populated collection of {@link CampaignPerformanceVideoItem} pojos + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + Results bulkUpdatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkUpdateOperation bulkUpdateOperation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * Bulk Update {@link CampaignPerformanceVideoItem} + * + * @param auth Authentication object ({@link BackstageAuthentication}) + * @param accountId To which {@link com.taboola.backstage.model.Account Account} the campaign belongs. Taken from {@link com.taboola.backstage.model.Account#getAccountId() Account.getAccountId()} + * @param bulkUpdateOperation {@link PerformanceVideoBulkUpdateOperation} + * @param bypassUrlResponseValidation Avoid URL validation + * @return Fully populated collection of {@link CampaignPerformanceVideoItem} pojos + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + Results bulkUpdatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkUpdateOperation bulkUpdateOperation, boolean bypassUrlResponseValidation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; } diff --git a/src/main/java/com/taboola/backstage/services/CampaignItemsServiceImpl.java b/src/main/java/com/taboola/backstage/services/CampaignItemsServiceImpl.java index eed1eb0..282fbd2 100644 --- a/src/main/java/com/taboola/backstage/services/CampaignItemsServiceImpl.java +++ b/src/main/java/com/taboola/backstage/services/CampaignItemsServiceImpl.java @@ -11,6 +11,10 @@ import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemMassiveUpdateOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItemOperation; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItem; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItemOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkCreateOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkUpdateOperation; import com.taboola.rest.api.internal.FieldsValidator; /** @@ -132,4 +136,82 @@ public CampaignItem deleteItem(BackstageAuthentication auth, String accountId, S String accessToken = auth.getToken().getAccessTokenForHeader(); return endpoint.deleteItem(accessToken, accountId, campaignId, itemId); } + + @Override + public Results readPerformanceVideoItems(BackstageAuthentication auth, String accountId, String campaignId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.getVideoCreatives(accessToken, accountId, campaignId); + } + + @Override + public CampaignPerformanceVideoItem readPerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.getVideoCreative(accessToken, accountId, campaignId, itemId); + } + + @Override + public CampaignPerformanceVideoItem createPerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, CampaignPerformanceVideoItemOperation item) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateCreateOperation(item); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.insertVideoCreative(accessToken, accountId, campaignId, item); + } + + @Override + public CampaignPerformanceVideoItem updatePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId, CampaignPerformanceVideoItemOperation item) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateUpdateOperation(item); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.updateVideoCreative(accessToken, accountId, campaignId, itemId, false, item); + } + + @Override + public CampaignPerformanceVideoItem updatePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId, CampaignPerformanceVideoItemOperation item, boolean bypassUrlResponseValidation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateUpdateOperation(item); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.updateVideoCreative(accessToken, accountId, campaignId, itemId, bypassUrlResponseValidation, item); + } + + @Override + public CampaignPerformanceVideoItem deletePerformanceVideoItem(BackstageAuthentication auth, String accountId, String campaignId, String itemId) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.deleteVideoCreative(accessToken, accountId, campaignId, itemId); + } + + @Override + public Results bulkCreatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkCreateOperation bulkCreateOperation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateCreateOperation(bulkCreateOperation); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.bulkCreateVideo(accessToken, accountId, bulkCreateOperation); + } + + @Override + public Results bulkUpdatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkUpdateOperation bulkUpdateOperation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateCreateOperation(bulkUpdateOperation); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.bulkUpdateVideo(accessToken, accountId, false, bulkUpdateOperation); + } + + @Override + public Results bulkUpdatePerformanceVideoItem(BackstageAuthentication auth, String accountId, PerformanceVideoBulkUpdateOperation bulkUpdateOperation, boolean bypassUrlResponseValidation) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + if(performValidations) { + FieldsValidator.validateCreateOperation(bulkUpdateOperation); + } + + String accessToken = auth.getToken().getAccessTokenForHeader(); + return endpoint.bulkUpdateVideo(accessToken, accountId, bypassUrlResponseValidation, bulkUpdateOperation); + } } From 3f5ffca7a8e13b782ea54fd0520c27b4598612ce Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 22:25:59 +0200 Subject: [PATCH 15/21] Removing read only field from operation obj --- .../media/campaigns/items/CampaignPerformanceVideoItem.java | 1 + .../items/CampaignPerformanceVideoItemOperation.java | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java index 32fbdb5..be588e5 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItem.java @@ -17,6 +17,7 @@ public class CampaignPerformanceVideoItem { protected String url; protected String title; protected String description; + @ReadOnly protected ItemApprovalState approvalState; protected Boolean isActive; @ReadOnly diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java index 9ed7940..aa40d4f 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignPerformanceVideoItemOperation.java @@ -37,11 +37,6 @@ public CampaignPerformanceVideoItemOperation setDescription(String description) return this; } - public CampaignPerformanceVideoItemOperation setApprovalState(ItemApprovalState approvalState) { - this.approvalState = approvalState; - return this; - } - public CampaignPerformanceVideoItemOperation setActive(Boolean active) { isActive = active; return this; From 8ba96922babde027d6528b82ad30dd0fecd2f648 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 22:54:14 +0200 Subject: [PATCH 16/21] Adding history report --- .../BackstageMediaReportsEndpoint.java | 10 +- .../model/media/reports/HistoryReport.java | 13 ++ .../model/media/reports/HistoryReportRow.java | 171 ++++++++++++++++++ .../services/AdvertiserReportsService.java | 14 ++ .../services/ReportsServiceImpl.java | 9 + 5 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/taboola/backstage/model/media/reports/HistoryReport.java create mode 100644 src/main/java/com/taboola/backstage/model/media/reports/HistoryReportRow.java diff --git a/src/main/java/com/taboola/backstage/internal/BackstageMediaReportsEndpoint.java b/src/main/java/com/taboola/backstage/internal/BackstageMediaReportsEndpoint.java index 358be29..d203a92 100644 --- a/src/main/java/com/taboola/backstage/internal/BackstageMediaReportsEndpoint.java +++ b/src/main/java/com/taboola/backstage/internal/BackstageMediaReportsEndpoint.java @@ -2,6 +2,7 @@ import com.taboola.backstage.exceptions.BackstageAPIException; import com.taboola.backstage.model.media.reports.CampaignSummaryReport; +import com.taboola.backstage.model.media.reports.HistoryReport; import com.taboola.backstage.model.media.reports.TopCampaignContentReport; import retrofit2.http.*; @@ -32,4 +33,11 @@ CampaignSummaryReport getCampaignSummary(@Header("Authorization") String authTok @Query("start_date") String startDate, @Query("end_date") String endDate, @QueryMap Map filters) throws BackstageAPIException; - } + + @GET(BackstagePaths.BACKSTAGE_API_PATH_PREFIX + "/{account_id}/reports/campaign-history/dimensions/by_account") + @Headers("Content-Type: application/json") + HistoryReport getCampaignHistoryByAccountReport(@Header("Authorization") String authToken, + @Path("account_id") String accountId, + @Query("start_date") String startDate, + @Query("end_date") String endDate) throws BackstageAPIException; +} diff --git a/src/main/java/com/taboola/backstage/model/media/reports/HistoryReport.java b/src/main/java/com/taboola/backstage/model/media/reports/HistoryReport.java new file mode 100644 index 0000000..7433f1b --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/reports/HistoryReport.java @@ -0,0 +1,13 @@ +package com.taboola.backstage.model.media.reports; + +import com.taboola.backstage.model.Report; + +/** + * Created by vladi + * Date 13/11/2023 + * Time 22:31 + * By Taboola + */ +public class HistoryReport extends Report { + +} diff --git a/src/main/java/com/taboola/backstage/model/media/reports/HistoryReportRow.java b/src/main/java/com/taboola/backstage/model/media/reports/HistoryReportRow.java new file mode 100644 index 0000000..e7de07a --- /dev/null +++ b/src/main/java/com/taboola/backstage/model/media/reports/HistoryReportRow.java @@ -0,0 +1,171 @@ +package com.taboola.backstage.model.media.reports; + +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * Created by vladi.m + * Date 13/11/2023 + * Time 22:31 + * Copyright Taboola + */ +public class HistoryReportRow { + private Long id; + private Long accountId; + private String accountName; + private Long campaignId; + private String campaignName; + private String changeType; + private String activityCode; + private String activityCodeDescription; + private String activityDetailsCode; + private String activityDetailsDescription; + private String oldValue; + private String newValue; + private String performer; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss.S") + private Date changeTime; + private String parametersDetails; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public Long getCampaignId() { + return campaignId; + } + + public void setCampaignId(Long campaignId) { + this.campaignId = campaignId; + } + + public String getCampaignName() { + return campaignName; + } + + public void setCampaignName(String campaignName) { + this.campaignName = campaignName; + } + + public String getChangeType() { + return changeType; + } + + public void setChangeType(String changeType) { + this.changeType = changeType; + } + + public String getActivityCode() { + return activityCode; + } + + public void setActivityCode(String activityCode) { + this.activityCode = activityCode; + } + + public String getActivityCodeDescription() { + return activityCodeDescription; + } + + public void setActivityCodeDescription(String activityCodeDescription) { + this.activityCodeDescription = activityCodeDescription; + } + + public String getActivityDetailsCode() { + return activityDetailsCode; + } + + public void setActivityDetailsCode(String activityDetailsCode) { + this.activityDetailsCode = activityDetailsCode; + } + + public String getActivityDetailsDescription() { + return activityDetailsDescription; + } + + public void setActivityDetailsDescription(String activityDetailsDescription) { + this.activityDetailsDescription = activityDetailsDescription; + } + + public String getOldValue() { + return oldValue; + } + + public void setOldValue(String oldValue) { + this.oldValue = oldValue; + } + + public String getNewValue() { + return newValue; + } + + public void setNewValue(String newValue) { + this.newValue = newValue; + } + + public String getPerformer() { + return performer; + } + + public void setPerformer(String performer) { + this.performer = performer; + } + + public Date getChangeTime() { + return changeTime; + } + + public void setChangeTime(Date changeTime) { + this.changeTime = changeTime; + } + + public String getParametersDetails() { + return parametersDetails; + } + + public void setParametersDetails(String parametersDetails) { + this.parametersDetails = parametersDetails; + } + + @Override + public String toString() { + return "HistoryReportRow{" + + "id=" + id + + ", accountId=" + accountId + + ", accountName='" + accountName + '\'' + + ", campaignId=" + campaignId + + ", campaignName='" + campaignName + '\'' + + ", changeType='" + changeType + '\'' + + ", activityCode='" + activityCode + '\'' + + ", activityCodeDescription='" + activityCodeDescription + '\'' + + ", activityDetailsCode='" + activityDetailsCode + '\'' + + ", activityDetailsDescription='" + activityDetailsDescription + '\'' + + ", oldValue='" + oldValue + '\'' + + ", newValue='" + newValue + '\'' + + ", performer='" + performer + '\'' + + ", changeTime=" + changeTime + + ", parametersDetails='" + parametersDetails + '\'' + + '}'; + } +} diff --git a/src/main/java/com/taboola/backstage/services/AdvertiserReportsService.java b/src/main/java/com/taboola/backstage/services/AdvertiserReportsService.java index 0f51dd7..af86f97 100644 --- a/src/main/java/com/taboola/backstage/services/AdvertiserReportsService.java +++ b/src/main/java/com/taboola/backstage/services/AdvertiserReportsService.java @@ -99,4 +99,18 @@ TopCampaignContentReport getTopCampaignContentReport(BackstageAuthentication aut */ CampaignSummaryReport getCampaignSummaryReport(BackstageAuthentication auth, String accountId, LocalDate startDate, LocalDate endDate, CampaignSummaryDimensions dimension, Map filters) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; + + /** + * The "History" report is an advertiser report. This report provide insight into changes done on advertiser and its entities + * + * @param auth Authentication object {@link BackstageAuthentication} + * @param accountId Specific {@link com.taboola.backstage.model.Account Account.getId()} + * @param startDate From {@link LocalDate} period + * @param endDate To {@link LocalDate} period + * @return Report data in form of {@link HistoryReport} object + * @throws BackstageAPIUnauthorizedException {@link com.taboola.backstage.model.auth.Token Token} is expired or bad credentials + * @throws BackstageAPIConnectivityException Connectivity issues (HTTP status 5xx) + * @throws BackstageAPIRequestException Bad request (HTTP status 4xx) + */ + HistoryReport getHistoryReport(BackstageAuthentication auth, String accountId, LocalDate startDate, LocalDate endDate) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException; } diff --git a/src/main/java/com/taboola/backstage/services/ReportsServiceImpl.java b/src/main/java/com/taboola/backstage/services/ReportsServiceImpl.java index 7847524..0f3ba4d 100644 --- a/src/main/java/com/taboola/backstage/services/ReportsServiceImpl.java +++ b/src/main/java/com/taboola/backstage/services/ReportsServiceImpl.java @@ -17,6 +17,7 @@ import com.taboola.backstage.model.media.reports.CampaignSummaryDimensions; import com.taboola.backstage.model.media.reports.CampaignSummaryOptionalFilters; import com.taboola.backstage.model.media.reports.CampaignSummaryReport; +import com.taboola.backstage.model.media.reports.HistoryReport; import com.taboola.backstage.model.media.reports.TopCampaignContentOptionalFilters; import com.taboola.backstage.model.media.reports.TopCampaignContentReport; import com.taboola.backstage.model.publishers.reports.RecirculationSummaryDimensions; @@ -94,6 +95,14 @@ public CampaignSummaryReport getCampaignSummaryReport(BackstageAuthentication au return report; } + @Override + public HistoryReport getHistoryReport(BackstageAuthentication auth, String accountId, LocalDate startDate, LocalDate endDate) throws BackstageAPIUnauthorizedException, BackstageAPIConnectivityException, BackstageAPIRequestException { + String accessToken = auth.getToken().getAccessTokenForHeader(); + return mediaReportsEndpoint.getCampaignHistoryByAccountReport(accessToken, accountId, + DATE_TIME_FORMATTER.format(startDate), + DATE_TIME_FORMATTER.format(endDate)); + } + private Map formatOptionalFilters(Map filters) { return filters.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getName(), Map.Entry::getValue)); } From abcd4f48568d32197739f4c35d9863a4341876a4 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 23:34:39 +0200 Subject: [PATCH 17/21] Removing read only field --- .../model/media/campaigns/items/CampaignItemOperation.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java index c015e8f..775743f 100644 --- a/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java +++ b/src/main/java/com/taboola/backstage/model/media/campaigns/items/CampaignItemOperation.java @@ -63,11 +63,6 @@ public CampaignItemOperation setViewabilityTag(ViewabilityTag viewabilityTag) { return this; } - public CampaignItemOperation setLearningState(CampaignItemsLearningState learningState) { - this.learningState = learningState; - return this; - } - public CampaignItemOperation setAppInstall(CampaignItemAppInstall appInstall) { this.appInstall = appInstall; return this; From 157b0edc4dcb07404e4aa0273cf1410970afed8e Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Mon, 13 Nov 2023 23:42:06 +0200 Subject: [PATCH 18/21] Listing new functions on class level doc --- .../taboola/backstage/services/CampaignItemsService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/taboola/backstage/services/CampaignItemsService.java b/src/main/java/com/taboola/backstage/services/CampaignItemsService.java index 81c18b0..f7277f4 100644 --- a/src/main/java/com/taboola/backstage/services/CampaignItemsService.java +++ b/src/main/java/com/taboola/backstage/services/CampaignItemsService.java @@ -33,6 +33,13 @@ *
{@link CampaignItemsService#createMassive} - Create an Items via providing title,thumbnail,url *
{@link CampaignItemsService#updateMassive} - Update an item - Update an existing Item. *
{@link CampaignItemsService#deleteMassive} - Delete (Stop) an Item - Move an existing Item to a 'STOPPED' status. + *
{@link CampaignItemsService#readPerformanceVideoItems} + *
{@link CampaignItemsService#readPerformanceVideoItem} + *
{@link CampaignItemsService#createPerformanceVideoItem} + *
{@link CampaignItemsService#updatePerformanceVideoItem} + *
{@link CampaignItemsService#deletePerformanceVideoItem} + *
{@link CampaignItemsService#bulkCreatePerformanceVideoItem} + *
{@link CampaignItemsService#bulkUpdatePerformanceVideoItem} *

* * From 85b2522ff9a14a5048b55c0957887c7c46ca6720 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Tue, 14 Nov 2023 20:59:43 +0200 Subject: [PATCH 19/21] Bump version --- pom.xml | 2 +- src/main/java/com/taboola/backstage/Backstage.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6f2c183..d2afea2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 com.taboola backstage-api-java-client - 1.1.4 + 1.1.5 ${project.groupId}:${project.artifactId} Backstage API Java Client diff --git a/src/main/java/com/taboola/backstage/Backstage.java b/src/main/java/com/taboola/backstage/Backstage.java index ab21e54..abebae9 100644 --- a/src/main/java/com/taboola/backstage/Backstage.java +++ b/src/main/java/com/taboola/backstage/Backstage.java @@ -181,7 +181,7 @@ public static class BackstageBuilder { private static final String DEFAULT_BACKSTAGE_HOST = "https://backstage.taboola.com/backstage/"; private static final String DEFAULT_AUTH_BACKSTAGE_HOST = "https://authentication.taboola.com/authentication/"; private static final String DEFAULT_USER_AGENT = "Taboola Java Client"; - private static final String VERSION = "1.1.4"; + private static final String VERSION = "1.1.5"; private static final SerializationConfig DEFAULT_SERIALIZATION_CONFIG = new SerializationConfig(); private String baseUrl; From 3f1acb00b96fc8c0f883fcc8b32f875a42ef39c7 Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Tue, 14 Nov 2023 21:21:43 +0200 Subject: [PATCH 20/21] Added unit test for history report --- .../services/ReportsServiceImplTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/java/com/taboola/backstage/services/ReportsServiceImplTest.java b/src/test/java/com/taboola/backstage/services/ReportsServiceImplTest.java index d78626d..30e44f8 100644 --- a/src/test/java/com/taboola/backstage/services/ReportsServiceImplTest.java +++ b/src/test/java/com/taboola/backstage/services/ReportsServiceImplTest.java @@ -93,6 +93,27 @@ public void testHappyFlow_TopCampaignContent() throws Exception { .getTopCampaignContentReport(auth.getToken().getAccessTokenForHeader(), "accountId", dateStr, dateStr, Collections.emptyMap()); } + @Test + public void testHappyFlow_History() throws Exception { + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + LocalDate date = LocalDate.of(2018, 1, 2); + String dateStr = DateTimeFormatter.ISO_LOCAL_DATE.format(date); + HistoryReport expected = generateDummyReport(HistoryReport.class, HistoryReportRow.class, 3); + when(advertiserReportMock.getCampaignHistoryByAccountReport(auth.getToken().getAccessTokenForHeader(), "accountId", dateStr, dateStr)).thenReturn(expected); + + HistoryReport actual = testInstance.getHistoryReport(auth, "accountId", date, date); + assertNotNull("Missing report", actual); + assertEquals("Invalid timezone", expected.getTimezone(), actual.getTimezone()); + assertEquals("Invalid last used rawdata update time", expected.getLastUsedRawdataUpdateTime(), actual.getLastUsedRawdataUpdateTime()); + Collection actualResults = actual.getResults(); + assertNotNull("Missing report results", actualResults); + assertEquals("Invalid number of rows", 3, actualResults.size()); + assertEquals("Invalid rows", expected.getResults(), actualResults); + + verify(advertiserReportMock, times(1)) + .getCampaignHistoryByAccountReport(auth.getToken().getAccessTokenForHeader(), "accountId", dateStr, dateStr); + } + @Test public void testHappyFlow_RevenueSummary() throws Exception { BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); From 0e8903ca5ba022e21b037b42c1fce6f71faeb63f Mon Sep 17 00:00:00 2001 From: vladimanaev Date: Tue, 14 Nov 2023 21:48:05 +0200 Subject: [PATCH 21/21] Added unit tests for performance video endpoints --- .../taboola/backstage/BackstageTestBase.java | 20 +++++ .../CampaignItemsServiceImplTest.java | 87 +++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/src/test/java/com/taboola/backstage/BackstageTestBase.java b/src/test/java/com/taboola/backstage/BackstageTestBase.java index 1136ff8..8c569f0 100644 --- a/src/test/java/com/taboola/backstage/BackstageTestBase.java +++ b/src/test/java/com/taboola/backstage/BackstageTestBase.java @@ -33,6 +33,10 @@ import com.taboola.backstage.model.media.campaigns.SharedBudgetOperation; import com.taboola.backstage.model.media.campaigns.items.CampaignItem; import com.taboola.backstage.model.media.campaigns.items.CampaignItemOperation; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItem; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItemOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkCreateOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkUpdateOperation; import com.taboola.backstage.model.media.campaigns.targeting.PostalTargeting; import uk.co.jemos.podam.api.PodamFactory; @@ -118,6 +122,22 @@ protected CampaignItem generateDummyCampaignItem() { return factory.manufacturePojo(CampaignItem.class); } + protected CampaignPerformanceVideoItem generateDummyCampaignPerformanceVideoItem() { + return factory.manufacturePojo(CampaignPerformanceVideoItem.class); + } + + protected CampaignPerformanceVideoItemOperation generateDummyCampaignPerformanceVideoItemOperation() { + return factory.manufacturePojo(CampaignPerformanceVideoItemOperation.class); + } + + protected PerformanceVideoBulkCreateOperation generateDummyPerformanceVideoBulkCreateOperation() { + return factory.manufacturePojo(PerformanceVideoBulkCreateOperation.class); + } + + protected PerformanceVideoBulkUpdateOperation generateDummyPerformanceVideoBulkUpdateOperation() { + return factory.manufacturePojo(PerformanceVideoBulkUpdateOperation.class); + } + protected CampaignItemOperation generateDummyCampaignItemOperation() { CampaignItemOperation campaignItemOperation = factory.manufacturePojo(CampaignItemOperation.class); campaignItemOperation.setUrl(null); diff --git a/src/test/java/com/taboola/backstage/services/CampaignItemsServiceImplTest.java b/src/test/java/com/taboola/backstage/services/CampaignItemsServiceImplTest.java index fce867d..80dc7d6 100644 --- a/src/test/java/com/taboola/backstage/services/CampaignItemsServiceImplTest.java +++ b/src/test/java/com/taboola/backstage/services/CampaignItemsServiceImplTest.java @@ -11,6 +11,10 @@ import org.junit.Before; import org.junit.Test; import com.taboola.backstage.BackstageTestBase; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItem; +import com.taboola.backstage.model.media.campaigns.items.CampaignPerformanceVideoItemOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkCreateOperation; +import com.taboola.backstage.model.media.campaigns.items.PerformanceVideoBulkUpdateOperation; import java.util.Collections; @@ -251,4 +255,87 @@ public void testDeleteItem() { assertEquals("Invalid campaign item", campaignItem, actual); verify(endpointMock, times(1)).deleteItem(any(), any(), any(), any()); } + + @Test + public void testReadPerformanceVideoItems() { + CampaignPerformanceVideoItem campaignItem = generateDummyCampaignPerformanceVideoItem(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + Results expectedResult = new Results<>(Collections.singletonList(campaignItem)); + when(endpointMock.getVideoCreatives(auth.getToken().getAccessTokenForHeader(),"accountId", "1")).thenReturn(expectedResult); + + Results actual = testInstance.readPerformanceVideoItems(auth, "accountId", "1"); + assertEquals("Invalid return value", expectedResult, actual); + assertEquals("Invalid results", expectedResult.getResults(), actual.getResults()); + verify(endpointMock, times(1)).getVideoCreatives(any(), any(), any()); + } + + @Test + public void testReadPerformanceVideoItem() { + CampaignPerformanceVideoItem campaignItem = generateDummyCampaignPerformanceVideoItem(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + when(endpointMock.getVideoCreative(auth.getToken().getAccessTokenForHeader(),"accountId", "1", "2")).thenReturn(campaignItem); + + CampaignPerformanceVideoItem actual = testInstance.readPerformanceVideoItem(auth, "accountId", "1", "2"); + assertEquals("Invalid return value", campaignItem, actual); + verify(endpointMock, times(1)).getVideoCreative(any(), any(), any(), any()); + } + + @Test + public void testCreatePerformanceVideoItem() { + CampaignPerformanceVideoItemOperation campaignItem = generateDummyCampaignPerformanceVideoItemOperation(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + when(endpointMock.insertVideoCreative(auth.getToken().getAccessTokenForHeader(),"accountId", "1", campaignItem)).thenReturn(campaignItem); + + CampaignPerformanceVideoItem actual = testInstance.createPerformanceVideoItem(auth, "accountId", "1", campaignItem); + assertEquals("Invalid return value", campaignItem, actual); + verify(endpointMock, times(1)).insertVideoCreative(any(), any(), any(), any()); + } + + @Test + public void testUpdatePerformanceVideoItem() { + CampaignPerformanceVideoItemOperation campaignItem = generateDummyCampaignPerformanceVideoItemOperation(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + when(endpointMock.updateVideoCreative(auth.getToken().getAccessTokenForHeader(),"accountId", "1", "2", false, campaignItem)).thenReturn(campaignItem); + + CampaignPerformanceVideoItem actual = testInstance.updatePerformanceVideoItem(auth, "accountId", "1", "2", campaignItem); + assertEquals("Invalid return value", campaignItem, actual); + verify(endpointMock, times(1)).updateVideoCreative(any(), any(), any(), any(), anyBoolean(), any()); + } + + @Test + public void testDeletePerformanceVideoItem() { + CampaignPerformanceVideoItemOperation campaignItem = generateDummyCampaignPerformanceVideoItemOperation(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + when(endpointMock.deleteVideoCreative(auth.getToken().getAccessTokenForHeader(),"accountId", "1", "2")).thenReturn(campaignItem); + + CampaignPerformanceVideoItem actual = testInstance.deletePerformanceVideoItem(auth, "accountId", "1", "2"); + assertEquals("Invalid return value", campaignItem, actual); + verify(endpointMock, times(1)).deleteVideoCreative(any(), any(), any(), any()); + } + + @Test + public void testBulkCreatePerformanceVideoItem() { + CampaignPerformanceVideoItemOperation campaignItem = generateDummyCampaignPerformanceVideoItemOperation(); + PerformanceVideoBulkCreateOperation bulkCreateOperation = generateDummyPerformanceVideoBulkCreateOperation(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + Results expectedResult = new Results<>(Collections.singletonList(campaignItem)); + when(endpointMock.bulkCreateVideo(auth.getToken().getAccessTokenForHeader(),"accountId", bulkCreateOperation)).thenReturn(expectedResult); + + Results actual = testInstance.bulkCreatePerformanceVideoItem(auth, "accountId", bulkCreateOperation); + assertEquals("Invalid return value", campaignItem, actual.getResults().iterator().next()); + verify(endpointMock, times(1)).bulkCreateVideo(any(), any(), any()); + } + + @Test + public void testBulkUpdatePerformanceVideoItem() { + CampaignPerformanceVideoItemOperation campaignItem = generateDummyCampaignPerformanceVideoItemOperation(); + PerformanceVideoBulkUpdateOperation bulkUpdateOperation = generateDummyPerformanceVideoBulkUpdateOperation(); + BackstageAuthentication auth = generateDummyClientCredentialsBackstageAuth(); + Results expectedResult = new Results<>(Collections.singletonList(campaignItem)); + when(endpointMock.bulkUpdateVideo(auth.getToken().getAccessTokenForHeader(),"accountId", false, bulkUpdateOperation)).thenReturn(expectedResult); + + Results actual = testInstance.bulkUpdatePerformanceVideoItem(auth, "accountId", bulkUpdateOperation); + assertEquals("Invalid return value", campaignItem, actual.getResults().iterator().next()); + verify(endpointMock, times(1)).bulkUpdateVideo(any(), any(), anyBoolean(), any()); + } }