twitter-ads 0.3.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|