twitter-ads 0.3.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/twitter-ads.rb +18 -0
- data/lib/twitter-ads/account.rb +20 -5
- data/lib/twitter-ads/audiences/tailored_audience.rb +4 -4
- data/lib/twitter-ads/campaign/app_list.rb +2 -2
- data/lib/twitter-ads/campaign/campaign.rb +4 -3
- data/lib/twitter-ads/campaign/funding_instrument.rb +2 -2
- data/lib/twitter-ads/campaign/line_item.rb +12 -14
- data/lib/twitter-ads/campaign/promotable_user.rb +2 -2
- data/lib/twitter-ads/campaign/targeting_criteria.rb +2 -2
- data/lib/twitter-ads/campaign/tweet.rb +5 -4
- data/lib/twitter-ads/creative/account_media.rb +36 -0
- data/lib/twitter-ads/creative/app_download_card.rb +2 -2
- data/lib/twitter-ads/creative/image_app_download_card.rb +2 -2
- data/lib/twitter-ads/creative/image_conversation_card.rb +2 -2
- data/lib/twitter-ads/creative/lead_gen_card.rb +2 -2
- data/lib/twitter-ads/creative/media_creative.rb +37 -0
- data/lib/twitter-ads/creative/promoted_account.rb +4 -3
- data/lib/twitter-ads/creative/promoted_tweet.rb +4 -3
- data/lib/twitter-ads/creative/video.rb +2 -2
- data/lib/twitter-ads/creative/video_app_download_card.rb +2 -2
- data/lib/twitter-ads/creative/video_conversation_card.rb +2 -2
- data/lib/twitter-ads/creative/website_card.rb +2 -2
- data/lib/twitter-ads/enum.rb +49 -2
- data/lib/twitter-ads/http/request.rb +2 -2
- data/lib/twitter-ads/resources/analytics.rb +129 -24
- data/lib/twitter-ads/resources/dsl.rb +1 -1
- data/lib/twitter-ads/targeting/reach_estimate.rb +17 -10
- data/lib/twitter-ads/targeting_criteria/app_store_category.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/behavior.rb +26 -0
- data/lib/twitter-ads/targeting_criteria/behavior_taxonomy.rb +23 -0
- data/lib/twitter-ads/targeting_criteria/device.rb +24 -0
- data/lib/twitter-ads/targeting_criteria/event.rb +32 -0
- data/lib/twitter-ads/targeting_criteria/interest.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/language.rb +21 -0
- data/lib/twitter-ads/targeting_criteria/location.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/network_operator.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/platform.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/platform_version.rb +23 -0
- data/lib/twitter-ads/targeting_criteria/tv_channel.rb +20 -0
- data/lib/twitter-ads/targeting_criteria/tv_genre.rb +20 -0
- data/lib/twitter-ads/targeting_criteria/tv_market.rb +22 -0
- data/lib/twitter-ads/targeting_criteria/tv_show.rb +22 -0
- data/lib/twitter-ads/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/twitter-ads/campaign/app_list_spec.rb +1 -1
- data/spec/twitter-ads/campaign/line_item_spec.rb +0 -22
- data/spec/twitter-ads/campaign/reach_estimate_spec.rb +16 -11
- data/spec/twitter-ads/campaign/tweet_spec.rb +2 -2
- data/spec/twitter-ads/client_spec.rb +1 -1
- data/spec/twitter-ads/creative/account_media_spec.rb +32 -0
- data/spec/twitter-ads/creative/media_creative_spec.rb +32 -0
- metadata +44 -22
- metadata.gz.sig +0 -0
@@ -23,7 +23,7 @@ module TwitterAds
|
|
23
23
|
# Creates a new Request object instance.
|
24
24
|
#
|
25
25
|
# @example
|
26
|
-
# request = Request.new(client, :get, '/
|
26
|
+
# request = Request.new(client, :get, '/1/accounts')
|
27
27
|
#
|
28
28
|
# @param client [Client] The Client object instance.
|
29
29
|
# @param method [Symbol] The HTTP method to be used.
|
@@ -47,7 +47,7 @@ module TwitterAds
|
|
47
47
|
# Executes the current Request object.
|
48
48
|
#
|
49
49
|
# @example
|
50
|
-
# request = Request.new(client, :get, '/
|
50
|
+
# request = Request.new(client, :get, '/1/accounts')
|
51
51
|
# request.perform
|
52
52
|
#
|
53
53
|
# @since 0.1.0
|
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# Copyright (C) 2015 Twitter, Inc.
|
3
3
|
|
4
|
+
require 'zlib'
|
5
|
+
require 'open-uri'
|
6
|
+
|
4
7
|
module TwitterAds
|
5
8
|
module Analytics
|
6
9
|
|
7
|
-
|
8
|
-
'TwitterAds::LineItem'
|
9
|
-
'TwitterAds::OrganicTweet'
|
10
|
-
'TwitterAds::
|
11
|
-
|
12
|
-
}.freeze # @api private
|
10
|
+
ANALYTICS_MAP = {
|
11
|
+
'TwitterAds::LineItem' => 'LINE_ITEM'.freeze,
|
12
|
+
'TwitterAds::OrganicTweet' => 'ORGANIC_TWEET'.freeze,
|
13
|
+
'TwitterAds::Creative::PromotedTweet' => 'PROMOTED_TWEET'.freeze
|
14
|
+
}.freeze
|
13
15
|
|
14
16
|
def self.included(klass)
|
15
17
|
klass.send :include, InstanceMethods
|
@@ -21,22 +23,21 @@ module TwitterAds
|
|
21
23
|
# Pulls a list of metrics for the current object instance.
|
22
24
|
#
|
23
25
|
# @example
|
24
|
-
#
|
26
|
+
# metric_groups = [:promoted_tweet_timeline_clicks, :promoted_tweet_search_clicks]
|
25
27
|
# object.stats(metrics)
|
26
28
|
#
|
27
|
-
# @param
|
29
|
+
# @param metric_groups [Array] A collection of metric groups to fetch.
|
28
30
|
# @param opts [Hash] An optional Hash of extended options.
|
29
31
|
# @option opts [Time] :start_time The starting time to use (default: 7 days ago).
|
30
32
|
# @option opts [Time] :end_time The end time to use (default: now).
|
31
33
|
# @option opts [Symbol] :granularity The granularity to use (default: :hour).
|
32
|
-
# @option opts [Symbol] :segmentation_type The segmentation type to use (default: none).
|
33
34
|
#
|
34
35
|
# @return [Array] The collection of stats requested.
|
35
36
|
#
|
36
37
|
# @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation
|
37
|
-
# @since
|
38
|
-
def stats(
|
39
|
-
self.class.stats(account, [id],
|
38
|
+
# @since 1.0.0
|
39
|
+
def stats(metric_groups, opts = {})
|
40
|
+
self.class.stats(account, [id], metric_groups, opts)
|
40
41
|
end
|
41
42
|
|
42
43
|
end
|
@@ -47,43 +48,147 @@ module TwitterAds
|
|
47
48
|
#
|
48
49
|
# @example
|
49
50
|
# ids = ['7o4em', 'oc9ce', '1c5lji']
|
50
|
-
#
|
51
|
-
# object.stats(account, ids,
|
51
|
+
# metric_groups = [MetricGroups.MOBILE_CONVERSION, MetricGroups.ENGAGEMENT]
|
52
|
+
# object.stats(account, ids, metric_groups)
|
52
53
|
#
|
53
54
|
# @param account [Account] The Account object instance.
|
54
55
|
# @param ids [Array] A collection of object IDs being targeted.
|
55
|
-
# @param
|
56
|
+
# @param metric_groups [Array] A collection of metric_groups to be fetched.
|
56
57
|
# @param opts [Hash] An optional Hash of extended options.
|
57
58
|
# @option opts [Time] :start_time The starting time to use (default: 7 days ago).
|
58
59
|
# @option opts [Time] :end_time The end time to use (default: now).
|
59
60
|
# @option opts [Symbol] :granularity The granularity to use (default: :hour).
|
60
|
-
# @option opts [Symbol] :
|
61
|
+
# @option opts [Symbol] :placement The placement of entity (default: ALL_ON_TWITTER).
|
61
62
|
#
|
62
63
|
# @return [Array] The collection of stats requested.
|
63
64
|
#
|
64
65
|
# @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation
|
65
|
-
# @since
|
66
|
-
|
66
|
+
# @since 1.0.0
|
67
|
+
|
68
|
+
def stats(account, ids, metric_groups, opts = {})
|
67
69
|
# set default metric values
|
68
|
-
end_time = opts.fetch(:end_time, Time.now)
|
70
|
+
end_time = opts.fetch(:end_time, (Time.now - Time.now.sec - (60 * Time.now.min)))
|
69
71
|
start_time = opts.fetch(:start_time, end_time - 604_800) # 7 days ago
|
70
72
|
granularity = opts.fetch(:granularity, :hour)
|
71
|
-
|
73
|
+
placement = opts.fetch(:placement, Placement::ALL_ON_TWITTER)
|
72
74
|
|
73
75
|
params = {
|
74
|
-
|
76
|
+
metric_groups: metric_groups.join(','),
|
75
77
|
start_time: TwitterAds::Utils.to_time(start_time, granularity),
|
76
78
|
end_time: TwitterAds::Utils.to_time(end_time, granularity),
|
77
|
-
granularity: granularity.to_s.upcase
|
79
|
+
granularity: granularity.to_s.upcase,
|
80
|
+
entity: ANALYTICS_MAP[name],
|
81
|
+
placement: placement
|
78
82
|
}
|
79
|
-
|
80
|
-
params[
|
83
|
+
|
84
|
+
params['entity_ids'] = ids.join(',')
|
81
85
|
|
82
86
|
resource = self::RESOURCE_STATS % { account_id: account.id }
|
83
87
|
response = Request.new(account.client, :get, resource, params: params).perform
|
84
88
|
response.body[:data]
|
85
89
|
end
|
86
90
|
|
91
|
+
# Create an asynchronous analytics job for a given ads account.
|
92
|
+
# A job_id is returned, which you can use to poll the
|
93
|
+
# GET /1/stats/jobs/accounts/:account_id endpoint, checking until the job is successful.
|
94
|
+
#
|
95
|
+
# @example
|
96
|
+
# ids = ['7o4em', 'oc9ce', '1c5lji']
|
97
|
+
# metric_groups = [MetricGroups.MOBILE_CONVERSION, MetricGroups.ENGAGEMENT]
|
98
|
+
# object.create_async_job(account, ids, metric_groups)
|
99
|
+
#
|
100
|
+
# @param account [Account] The Account object instance.
|
101
|
+
# @param ids [Array] A collection of object IDs being targeted.
|
102
|
+
# @param metric_groups [Array] A collection of metric_groups to be fetched.
|
103
|
+
# @param opts [Hash] An optional Hash of extended options.
|
104
|
+
# @option opts [Time] :start_time The starting time to use (default: 7 days ago).
|
105
|
+
# @option opts [Time] :end_time The end time to use (default: now).
|
106
|
+
# @option opts [Symbol] :granularity The granularity to use (default: :hour).
|
107
|
+
# @option opts [Symbol] :placement The placement of entity (default: ALL_ON_TWITTER).
|
108
|
+
# @option opts [Symbol] :segmentation_type The segmentation type to use (default: none).
|
109
|
+
#
|
110
|
+
# @return The response of creating job
|
111
|
+
#
|
112
|
+
# @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation
|
113
|
+
# @sync 1.0.0
|
114
|
+
|
115
|
+
def create_async_job(account, ids, metric_groups, opts = {})
|
116
|
+
# set default metric values
|
117
|
+
end_time = opts.fetch(:end_time, (Time.now - Time.now.sec - (60 * Time.now.min)))
|
118
|
+
start_time = opts.fetch(:start_time, end_time - 604_800) # 7 days ago
|
119
|
+
granularity = opts.fetch(:granularity, :hour)
|
120
|
+
placement = opts.fetch(:placement, Placement::ALL_ON_TWITTER)
|
121
|
+
segmentation_type = opts.fetch(:segmentation_type, nil)
|
122
|
+
|
123
|
+
params = {
|
124
|
+
metric_groups: metric_groups.join(','),
|
125
|
+
start_time: TwitterAds::Utils.to_time(start_time, granularity),
|
126
|
+
end_time: TwitterAds::Utils.to_time(end_time, granularity),
|
127
|
+
granularity: granularity.to_s.upcase,
|
128
|
+
entity: ANALYTICS_MAP[name],
|
129
|
+
placement: placement
|
130
|
+
}
|
131
|
+
|
132
|
+
params[:segmentation_type] = segmentation_type.to_s.upcase if segmentation_type
|
133
|
+
params['entity_ids'] = ids.join(',')
|
134
|
+
|
135
|
+
resource = self::RESOURCE_ASYNC_STATS % { account_id: account.id }
|
136
|
+
puts 'my resource is ' + resource
|
137
|
+
response = Request.new(account.client, :post, resource, params: params).perform
|
138
|
+
response.body[:data]
|
139
|
+
end
|
140
|
+
|
141
|
+
# Check async job status.
|
142
|
+
# GET /1/stats/jobs/accounts/:account_id
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# TwitterAds::LineItem.check_async_job_status(account, job_id: '1357343438724431305')
|
146
|
+
#
|
147
|
+
# @param account [Account] The Account object instance.
|
148
|
+
# @option opts [String] :job_id The starting time to use (default: 7 days ago).
|
149
|
+
#
|
150
|
+
# @return A cursor of job statuses
|
151
|
+
|
152
|
+
def check_async_job_status(account, opts = {})
|
153
|
+
# set default values
|
154
|
+
job_id = opts.fetch(:job_id, nil)
|
155
|
+
params = {}
|
156
|
+
params[:job_id] = job_id if job_id
|
157
|
+
|
158
|
+
resource = self::RESOURCE_ASYNC_STATS % { account_id: account.id }
|
159
|
+
request = Request.new(account.client, :get, resource, params: params)
|
160
|
+
Cursor.new(nil, request, init_with: [account])
|
161
|
+
end
|
162
|
+
|
163
|
+
# Fetch async job data for a completed job.
|
164
|
+
# Raises HTTP 404 exception, otherwise retries up to 5 times with exponential backoff.
|
165
|
+
#
|
166
|
+
# @example
|
167
|
+
# response_data = TwitterAds::LineItem.fetch_async_job_data(account, file_url)
|
168
|
+
#
|
169
|
+
# @param data_url [String] The URL from the successful completion of an async job.
|
170
|
+
#
|
171
|
+
# @return A cursor of job statuses
|
172
|
+
|
173
|
+
def fetch_async_job_data(data_url)
|
174
|
+
tries = 0
|
175
|
+
begin
|
176
|
+
tries += 1
|
177
|
+
raw_file = open(data_url)
|
178
|
+
unzipped_file = Zlib::GzipReader.new(raw_file)
|
179
|
+
response_data = unzipped_file.read
|
180
|
+
response = JSON.parse(response_data)
|
181
|
+
response['data']
|
182
|
+
rescue OpenURI::HTTPError => e
|
183
|
+
unless e.io.status[0] == '404'
|
184
|
+
if tries < 5
|
185
|
+
sleep(2**tries)
|
186
|
+
retry
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
87
192
|
end
|
88
193
|
|
89
194
|
end
|
@@ -13,20 +13,20 @@ module TwitterAds
|
|
13
13
|
# account,
|
14
14
|
# 'PROMOTED_TWEETS',
|
15
15
|
# 'WEBSITE_CLICKS',
|
16
|
-
#
|
16
|
+
# 5500000,
|
17
|
+
# 30000000,
|
17
18
|
# similar_to_followers_of_user: 2153688540,
|
18
19
|
# gender: 2
|
19
20
|
# )
|
20
21
|
#
|
21
22
|
# @param client [Client] The Client object instance.
|
22
|
-
# @param account [Account] The Ads Account instance for this request.
|
23
23
|
# @param product_type [String] The product type being targeted.
|
24
24
|
# @param objective [String] The objective being targeted.
|
25
|
-
# @param
|
25
|
+
# @param campaign_daily_budget_amount_local_micro [Long] Daily budget in micros.
|
26
26
|
# @param opts [Hash] A Hash of extended options.
|
27
27
|
#
|
28
|
-
# @option opts [String] :bid_type The bidding mechanism.
|
29
28
|
# @option opts [Long] :bid_amount_local_micro Bid amount in local currency micros.
|
29
|
+
# @option opts [String] :bid_type The bidding mechanism.
|
30
30
|
# @option opts [String] :currency ISO-4217 Currency code for bid amount.
|
31
31
|
# @option opts [String] :followers_of_users Comma-separated user IDs.
|
32
32
|
# @option opts [String] :similar_to_followers_of_users Comma-separated user IDs.
|
@@ -44,14 +44,20 @@ module TwitterAds
|
|
44
44
|
# @option opts [String] :campaign engagement Campaign ID for Tweet Engager Retargeting.
|
45
45
|
# @option opts [String] :user_engagement Promoted User ID for Tweet Engager Retargeting.
|
46
46
|
# @option opts [String] :engagement_type engagement type for Tweet Engager Retargeting.
|
47
|
+
# @option opts [String] :network_operators Network operators to target
|
48
|
+
# @option opts [String] :app_store_categories App store categories to target.
|
49
|
+
# @option opts [String] :app_store_categories_expanded App store categories with lookalikes.
|
47
50
|
#
|
48
51
|
# @return [Hash] A hash containing count and infinite_bid_count.
|
49
52
|
#
|
50
|
-
# @since 0.
|
51
|
-
# @see https://dev.twitter.com/ads/reference/get/accounts/%3Aaccount_id/reach_estimate
|
52
|
-
def fetch(account, product_type, objective,
|
53
|
-
|
54
|
-
|
53
|
+
# @since 1.0.0
|
54
|
+
# @see https://dev.twitter.com/ads/reference/1/get/accounts/%3Aaccount_id/reach_estimate
|
55
|
+
def fetch(account, product_type, objective, campaign_daily_budget,
|
56
|
+
opts = {})
|
57
|
+
resource = "/1/accounts/#{account.id}/reach_estimate"
|
58
|
+
params = { product_type: product_type, objective: objective,
|
59
|
+
campaign_daily_budget_amount_local_micro: campaign_daily_budget
|
60
|
+
}.merge!(opts)
|
55
61
|
|
56
62
|
# The response value count is "bid sensitive", we default to bid_type=AUTO here to preserve
|
57
63
|
# expected behavior despite an API change that occurred in December 2015.
|
@@ -59,7 +65,8 @@ module TwitterAds
|
|
59
65
|
params = { bid_type: 'AUTO' }.merge!(params)
|
60
66
|
end
|
61
67
|
|
62
|
-
response = TwitterAds::Request.new(account.client, :get,
|
68
|
+
response = TwitterAds::Request.new(account.client, :get,
|
69
|
+
resource, params: params).perform
|
63
70
|
response.body[:data]
|
64
71
|
end
|
65
72
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class AppStoreCategory
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :name, read_only: true
|
11
|
+
property :os_type, read_only: true
|
12
|
+
property :targeting_type, read_only: true
|
13
|
+
property :targeting_value, read_only: true
|
14
|
+
|
15
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/app_store_categories'.freeze # @api private
|
16
|
+
|
17
|
+
def initialize(account)
|
18
|
+
@account = account
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class Behavior
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :id, read_only: true
|
11
|
+
property :name, read_only: true
|
12
|
+
property :targeting_type, read_only: true
|
13
|
+
property :targeting_value, read_only: true
|
14
|
+
property :audience_code, read_only: true
|
15
|
+
property :country_code, read_only: true
|
16
|
+
property :partner_source, read_only: true
|
17
|
+
property :targetable_type, read_only: true
|
18
|
+
|
19
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/behaviors'.freeze # @api private
|
20
|
+
|
21
|
+
def initialize(account)
|
22
|
+
@account = account
|
23
|
+
self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class BehaviorTaxonomy
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :id, read_only: true
|
11
|
+
property :name, read_only: true
|
12
|
+
property :parent_id, read_only: true
|
13
|
+
property :created_at, read_only: true
|
14
|
+
property :updated_at, read_only: true
|
15
|
+
|
16
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/behavior_taxonomies'.freeze # @api private
|
17
|
+
|
18
|
+
def initialize(account)
|
19
|
+
@account = account
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class Device
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :id, read_only: true
|
11
|
+
property :name, read_only: true
|
12
|
+
property :targeting_type, read_only: true
|
13
|
+
property :targeting_value, read_only: true
|
14
|
+
property :platform, read_only: true
|
15
|
+
property :manufacturer, read_only: true
|
16
|
+
|
17
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/devices'.freeze # @api private
|
18
|
+
|
19
|
+
def initialize(account)
|
20
|
+
@account = account
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class Event
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :id, read_only: true
|
11
|
+
property :name, read_only: true
|
12
|
+
property :reach, read_only: true
|
13
|
+
property :start_time, read_only: true
|
14
|
+
property :end_time, read_only: true
|
15
|
+
property :top_users, read_only: true
|
16
|
+
property :top_tweets, read_only: true
|
17
|
+
property :top_hashtags, read_only: true
|
18
|
+
property :country_code, read_only: true
|
19
|
+
property :is_global, read_only: true
|
20
|
+
property :category, read_only: true
|
21
|
+
property :gender_breakdown_percentage, read_only: true
|
22
|
+
property :device_breakdown_percentage, read_only: true
|
23
|
+
property :country_breakdown_percentage, read_only: true
|
24
|
+
|
25
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/events'.freeze # @api private
|
26
|
+
|
27
|
+
def initialize(account)
|
28
|
+
@account = account
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright (C) 2015 Twitter, Inc.
|
3
|
+
|
4
|
+
module TwitterAds
|
5
|
+
class Interest
|
6
|
+
|
7
|
+
include TwitterAds::DSL
|
8
|
+
include TwitterAds::Resource
|
9
|
+
|
10
|
+
property :name, read_only: true
|
11
|
+
property :targeting_type, read_only: true
|
12
|
+
property :targeting_value, read_only: true
|
13
|
+
property :localized_name, read_only: true
|
14
|
+
|
15
|
+
RESOURCE_COLLECTION = '/1/targeting_criteria/interests'.freeze # @api private
|
16
|
+
|
17
|
+
def initialize(account)
|
18
|
+
@account = account
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|