Skip to content

Commit

Permalink
Ads API V8 (#235)
Browse files Browse the repository at this point in the history
* Support TA parameter owner_account_id (#234)

* Product renaming for v8 (#233)

* Ads API v8 (#241)

* bump version

* targeted audiences support

Co-authored-by: Tushar Bhushan <[email protected]>
  • Loading branch information
osowskit and tushdante authored Oct 28, 2020
1 parent 3bce052 commit c04923e
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 13 deletions.
4 changes: 2 additions & 2 deletions examples/batch_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
line_item_1.name = 'my first ad'
line_item_1.product_type = TwitterAds::Product::PROMOTED_TWEETS
line_item_1.placements = [TwitterAds::Placement::ALL_ON_TWITTER]
line_item_1.objective = TwitterAds::Objective::TWEET_ENGAGEMENTS
line_item_1.objective = TwitterAds::Objective::ENGAGEMENTS
line_item_1.bid_amount_local_micro = 10_000
line_item_1.entity_status = EntityStatus::PAUSED

Expand All @@ -55,7 +55,7 @@
line_item_2.name = 'my second ad'
line_item_2.product_type = TwitterAds::Product::PROMOTED_TWEETS
line_item_2.placements = [TwitterAds::Placement::ALL_ON_TWITTER]
line_item_2.objective = TwitterAds::Objective::TWEET_ENGAGEMENTS
line_item_2.objective = TwitterAds::Objective::ENGAGEMENTS
line_item_2.bid_amount_local_micro = 20_000
line_item_2.entity_status = EntityStatus::PAUSED

Expand Down
2 changes: 1 addition & 1 deletion examples/metric_filtering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class Metrics
:video,
:other
],
tweet_engagements: [
engagements: [
:conversion,
:engagement,
:media,
Expand Down
2 changes: 1 addition & 1 deletion examples/quick_start.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
line_item.name = 'my first ad'
line_item.product_type = Product::PROMOTED_TWEETS
line_item.placements = [Placement::ALL_ON_TWITTER]
line_item.objective = Objective::TWEET_ENGAGEMENTS
line_item.objective = Objective::ENGAGEMENTS
line_item.bid_amount_local_micro = 10_000
line_item.entity_status = EntityStatus::PAUSED
line_item.save
Expand Down
57 changes: 56 additions & 1 deletion lib/twitter-ads/audiences/tailored_audience.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TailoredAudience
property :audience_size, read_only: true
property :audience_type, read_only: true
property :metadata, read_only: true
property :owner_account_id, read_only: true
property :partner_source, read_only: true
property :reasons_not_targetable, read_only: true
property :targetable, type: :bool, read_only: true
Expand Down Expand Up @@ -91,7 +92,7 @@ def delete!
from_response(response.body[:data])
end

# This is a private API and requires whitelisting from Twitter.
# This is a private API and requires allowlisting from Twitter.
#
# This endpoint will allow partners to add, update and remove users from a given
# tailored_audience_id.
Expand Down Expand Up @@ -137,6 +138,60 @@ def users(params)
[success_count, total_count]
end

# Retrieves the entites targeting the current tailored audience instance.
#
# @example
# audience.targeted(with_active=true)
#
# @param with_active [bool] Include active/inactive
#
# @since 8.0.0
#
# @return [self] Returns a Cursor instance of the targeted entities.
def targeted(opts = {})
validate_loaded
params = {}.merge!(opts)
TargetedTailoredAudience.load(account, id, params)
end

def validate_loaded
raise ArgumentError.new(
"Error! #{self.class} object not yet initialized, " \
"call #{self.class}.load first") if id.nil?
end
end

class TargetedTailoredAudience

include TwitterAds::DSL
include TwitterAds::Resource

attr_reader :account

# read-only
property :campaign_id, read_only: true
property :campaign_name, read_only: true
property :line_items, read_only: true

RESOURCE_TARGETED = "/#{TwitterAds::API_VERSION}/" \
'accounts/%{account_id}/tailored_audiences/%{id}/targeted' # @api private

def initialize(account)
@account = account
self
end

class << self

def load(account, tailored_audience_id, params)
resource = RESOURCE_TARGETED % { account_id: account.id, id: tailored_audience_id }
request = TwitterAds::Request.new(account.client,
:get,
resource,
params: params)
Cursor.new(self, request, init_with: [account])
end
end
end

class TailoredAudiencePermission
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter-ads/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

module TwitterAds

API_VERSION = '7'
API_VERSION = '8'

# The Ads API Client class which functions as a
# container for basic API consumer information.
Expand Down
7 changes: 3 additions & 4 deletions lib/twitter-ads/enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ module Enum
module Objective
APP_ENGAGEMENTS = 'APP_ENGAGEMENTS'
APP_INSTALLS = 'APP_INSTALLS'
ENGAGEMENTS = 'ENGAGEMENTS'
FOLLOWERS = 'FOLLOWERS'
LEAD_GENERATION = 'LEAD_GENERATION'
TWEET_ENGAGEMENTS = 'TWEET_ENGAGEMENTS'
PREROLL_VIEWS = 'PREROLL_VIEWS'
REACH = 'REACH'
VIDEO_VIEWS = 'VIDEO_VIEWS'
WEBSITE_CLICKS = 'WEBSITE_CLICKS'
WEBSITE_CONVERSIONS = 'WEBSITE_CONVERSIONS'

end

module Product
Expand Down
2 changes: 1 addition & 1 deletion lib/twitter-ads/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# Copyright (C) 2019 Twitter, Inc.

module TwitterAds
VERSION = '7.0.1'
VERSION = '8.0.0'
end
3 changes: 3 additions & 0 deletions spec/fixtures/tailored_audiences_all.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
],
"audience_type": "WEB",
"id": "abc2",
"owner_account_id": "18ce54uhdu0",
"reasons_not_targetable": [
"TOO_SMALL"
],
Expand All @@ -33,6 +34,7 @@
],
"audience_type": "CRM",
"id": "abc1",
"owner_account_id": "18ce54uhdu0",
"reasons_not_targetable": [],
"list_type": "DEVICE_ID",
"created_at": "2014-05-22T17:37:12Z",
Expand All @@ -50,6 +52,7 @@
],
"audience_type": "CRM",
"id": "abc3",
"owner_account_id": "18ce54uhdu0",
"reasons_not_targetable": [
"TOO_SMALL"
],
Expand Down
33 changes: 33 additions & 0 deletions spec/fixtures/targeted_audiences.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"request": {
"params": {
"account_id": "2iqph",
"tailored_audience_id": "abc2"
}
},
"next_cursor": null,
"data": [
{
"campaign_id": "59hod",
"campaign_name": "test-campaign",
"line_items": [
{
"id": "5gzog",
"name": "test-line-item",
"servable": true
}
]
},
{
"campaign_id": "arja7",
"campaign_name": "Untitled campaign",
"line_items": [
{
"id": "bjw1q",
"name": null,
"servable": true
}
]
}
]
}
27 changes: 25 additions & 2 deletions spec/twitter-ads/audiences/tailored_audience_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@

before(:each) do
stub_fixture(:get, :accounts_all, "#{ADS_API}/accounts")
stub_fixture(:get, :accounts_load, "#{ADS_API}/accounts/2iqph")
stub_fixture(:get,
:tailored_audiences_load,
"#{ADS_API}/accounts/2iqph/tailored_audiences/abc2?with_deleted=true")
stub_fixture(:get,
:targeted_audiences,
"#{ADS_API}/accounts/2iqph/tailored_audiences/abc2/targeted")
end

let(:client) do
Expand All @@ -20,7 +25,7 @@
end

let(:account) { client.accounts.first }

let(:tailored_audience) { described_class.load(account, 'abc2') }
# check model properties
subject { described_class.new(account) }

Expand All @@ -29,6 +34,7 @@
created_at
updated_at
deleted
owner_account_id
audience_size
audience_type
metadata
Expand All @@ -42,4 +48,21 @@

include_examples 'object property check', read, write

describe '#targeted' do

let(:cursor) { tailored_audience.targeted }

it 'has all the correct properties' do
result = cursor.first
expect(result).to eq(cursor.instance_variable_get('@collection').first)
expect(result).to be_instance_of(TwitterAds::TargetedTailoredAudience)
expect(cursor).to be_instance_of(Cursor)
end

it 'raises error when TailoredAudience is not loaded' do
result = TwitterAds::TailoredAudience.new(account)
expect(result).to receive(:validate_loaded).and_call_original
expect { result.targeted }.to raise_error(ArgumentError)
end
end
end

0 comments on commit c04923e

Please sign in to comment.