embulk-input-yahoo_ads 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eecaec2da4f039d9da8f36dbd6b66119f2da9071
4
+ data.tar.gz: 04798501ab716b74d6babd0ab2b228c2cbf08b41
5
+ SHA512:
6
+ metadata.gz: 5d535779e9ee6ac79a3eb700596ccadb665ce5cbb9955aa50268b7a9edd77c72c658f0b7fa46468cd8e59a1eff7bba358439b0e9968506df2f3b3555391e672d
7
+ data.tar.gz: bf7b42a68a4423aad415f20bb5eb5421121cac9ba5ca2fb9c1d7f3432637e05b8f205837fe17eedfc0effb3e1282b0584301303c74a40dbf3c72affd7b0d7658
@@ -0,0 +1,7 @@
1
+ *~
2
+ /pkg/
3
+ /tmp/
4
+ /.bundle/
5
+ /Gemfile.lock
6
+ /vendor/bundle/
7
+ /workspaces/
@@ -0,0 +1 @@
1
+ jruby-9.1.5.0
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org/'
2
+ gemspec
@@ -0,0 +1,21 @@
1
+
2
+ MIT License
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,50 @@
1
+ # Yahoo Ads input plugin for Embulk
2
+ Embulk input plugin for Yahoo Promotion Ads.
3
+
4
+ ## Overview
5
+ * **Plugin type**: input
6
+ * **Resume supported**: no
7
+ * **Cleanup supported**: no
8
+ * **Guess supported**: no
9
+
10
+ ## Configuration
11
+ - **location**: 利用するAPIのlocation。検索広告とディスプレイ広告で異なる. (string, required)
12
+ - **version**: 利用するAPIのlocation。検索広告とディスプレイ広告で異なる. (string, required)
13
+ - **license**: Yahoo社から提供される認証情報 (string, required)
14
+ - **api_account**: Yahoo社から提供される認証情報 (string, required)
15
+ - **api_password**: API認証のためのパスワード (string, required)
16
+ - **namespace**: 利用するAPIのlocation。検索広告とディスプレイ広告で異なる. (string, required)
17
+ - **report_type**: レポートタイプ (string, required)
18
+ - **account_id**: 取得するアカウントのID (string, required)
19
+ - **date_range_min**: 取得するレポート期間の開始日. フォーマットは"YYYYMMDD" (string, required)
20
+ - **date_range_max**: 取得するレポート期間の終了日. フォーマットは"YYYYMMDD" (string, required)
21
+ - **columns**: 取得するレポートの列 (array, required)
22
+
23
+ ## Example
24
+ ```yaml
25
+ in:
26
+ type: yahoo_ads
27
+ location: xxxxx.yahooapis.jp
28
+ version: Vx.x
29
+ license: xxxx-xxxx-xxxx-xxxx
30
+ api_account: yyyy-yyyy-yyyy-yyyy
31
+ api_password: xyz
32
+ namespace: http://abc.yahooapis.jp/V0
33
+ report_type: CAMPAIGN
34
+ account_id: 000000000
35
+ date_range_min: 20171201
36
+ date_range_max: 20171210
37
+ columns:
38
+ - CAMPAIGN_NAME
39
+ - DAY
40
+ - IMPS
41
+ - CLICK
42
+ - COST
43
+ - CONVERSIONS
44
+ ```
45
+
46
+
47
+ ## Build
48
+ ```
49
+ $ rake
50
+ ```
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: :build
@@ -0,0 +1,22 @@
1
+
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "embulk-input-yahoo_ads"
4
+ spec.version = "0.1.0"
5
+ spec.authors = ["ryota.yamada"]
6
+ spec.summary = "Yahoo Ads input plugin for Embulk"
7
+ spec.description = "Loads records from Yahoo Ads."
8
+ spec.email = ["ryota.yamada@principle-c.com"]
9
+ spec.licenses = ["MIT"]
10
+ spec.homepage = "https://github.com/principle-c/embulk-input-yahoo_ads"
11
+
12
+ spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
13
+ spec.test_files = spec.files.grep(%r{^(test|spec)/})
14
+ spec.require_paths = ["lib"]
15
+
16
+ spec.add_dependency "savon", "~> 2.0"
17
+ spec.add_dependency "nokogiri", "~> 1.8.1"
18
+
19
+ spec.add_development_dependency 'embulk', ['>= 0.8.30']
20
+ spec.add_development_dependency 'bundler', ['>= 1.10.6']
21
+ spec.add_development_dependency 'rake', ['>= 10.0']
22
+ end
@@ -0,0 +1,23 @@
1
+ in:
2
+ type: yahoo_ads
3
+ location: xxxxx.yahooapis.jp
4
+ version: Vx.x
5
+ license: xxxx-xxxx-xxxx-xxxx
6
+ api_account: yyyy-yyyy-yyyy-yyyy
7
+ api_password: xyz
8
+ namespace: http://abc.yahooapis.jp/V0
9
+ report_type: CAMPAIGN
10
+ account_id: 000000000
11
+ date_range_min: 20171201
12
+ date_range_max: 20171210
13
+ columns:
14
+ - CAMPAIGN_NAME
15
+ - DAY
16
+ - IMPS
17
+ - CLICK
18
+ - COST
19
+ - CONVERSIONS
20
+ out:
21
+ type: stdout
22
+
23
+
@@ -0,0 +1,13 @@
1
+ require "embulk/input/yahoo_ads/auth_config"
2
+ require "embulk/input/yahoo_ads/client"
3
+ require "embulk/input/yahoo_ads/column"
4
+ require "embulk/input/yahoo_ads/location_service"
5
+ require "embulk/input/yahoo_ads/report_client"
6
+ require "embulk/input/yahoo_ads/version"
7
+ require "embulk/input/yahoo_ads/plugin"
8
+ module Embulk
9
+ module Input
10
+ module YahooAds
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ class AuthConfig
5
+ def initialize(options)
6
+ @location = options[:location]
7
+ @version = options[:version]
8
+ @license = options[:license]
9
+ @api_account = options[:api_account]
10
+ @api_password = options[:api_password]
11
+ @namespace = options[:namespace]
12
+ end
13
+
14
+ def location; @location end
15
+ def version; @version end
16
+ def license; @license end
17
+ def api_account; @api_account end
18
+ def api_password; @api_password end
19
+ def namespace; @namespace end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ class Client
5
+ def initialize(account_id, auth_config)
6
+ @account_id = account_id
7
+ @auth_config = auth_config
8
+ @locationService = LocationService.build(account_id, auth_config)
9
+ end
10
+
11
+ def invoke(service_name, action, params)
12
+ s = self.service(service_name)
13
+ ::Embulk.logger.info "SOAP Request: #{s.wsdl.document}"
14
+ s.call(action, params).body
15
+ end
16
+
17
+ def service(name)
18
+ ::Savon::Client.new({
19
+ wsdl: "https://#{@auth_config.location}/services/#{@auth_config.version}/#{name}?wsdl",
20
+ endpoint: "https://#{@locationService.invoke}/services/#{@auth_config.version}/#{name}",
21
+ namespace: @auth_config.namespace,
22
+ soap_header: {
23
+ "tns:RequestHeader": {
24
+ "tns:license": @auth_config.license,
25
+ "tns:apiAccountId": @auth_config.api_account,
26
+ "tns:apiAccountPassword": @auth_config.api_password,
27
+ }
28
+ }
29
+ })
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,227 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ class Column
5
+ def self.all
6
+ [
7
+ { :request_name => "ADGROUP_DESKTOP_BID_MODIFIER", :xml_name => "desktopBidAdj", :type => :double },
8
+ { :request_name => "ADGROUP_MOBILE_BID_MODIFIER", :xml_name => "mobileBidAdj", :type => :double },
9
+ { :request_name => "ADGROUP_TABLET_BID_MODIFIER", :xml_name => "tabletBidAdj", :type => :double },
10
+ { :request_name => "ALL_CONV", :xml_name => "allConv", :type => :double },
11
+ { :request_name => "ALL_CONV_RATE", :xml_name => "allConvRate", :type => :double },
12
+ { :request_name => "ALL_CONV_VALUE", :xml_name => "allConvValue", :type => :double },
13
+ { :request_name => "AVG_CPC", :xml_name => "averageCpc", :type => :double },
14
+ { :request_name => "AVG_CPV", :xml_name => "avgCpv", :type => :double },
15
+ { :request_name => "AVG_DELIVER_RANK", :xml_name => "averagePosition", :type => :double },
16
+ { :request_name => "AVG_DURATION_VIDEO_VIEWED", :xml_name => "avgDurationVideoViewed", :type => :double },
17
+ { :request_name => "AVG_PERCENT_VIDEO_VIEWED", :xml_name => "avgPercentVideoViewed", :type => :double },
18
+ { :request_name => "BUDGET_LOST_IMPRESSION_SHARE", :xml_name => "budgetLostImpressionShare", :type => :double },
19
+ { :request_name => "CAMPAIGN_DESKTOP_BID_MODIFIER", :xml_name => "desktopBidAdj", :type => :double },
20
+ { :request_name => "CAMPAIGN_MOBILE_BID_MODIFIER", :xml_name => "mobileBidAdj", :type => :double },
21
+ { :request_name => "CAMPAIGN_TABLET_BID_MODIFIER", :xml_name => "tabletBidAdj", :type => :double },
22
+ { :request_name => "CLICK_RATE", :xml_name => "ctr", :type => :double },
23
+ { :request_name => "CONVERSIONS", :xml_name => "conversions", :type => :double },
24
+ { :request_name => "CONVERSION_RATE_OLD", :xml_name => "totalConversionRateOld", :type => :double },
25
+ { :request_name => "CONV_RATE", :xml_name => "convRate", :type => :double },
26
+ { :request_name => "CONV_VALUE", :xml_name => "convValue", :type => :double },
27
+ { :request_name => "COST_PER_ALL_CONV", :xml_name => "costPerAllConv", :type => :double },
28
+ { :request_name => "COST_PER_CONV", :xml_name => "costPerConv", :type => :double },
29
+ { :request_name => "CPA_OLD", :xml_name => "costTotalConversionsOld", :type => :double },
30
+ { :request_name => "EXACT_MATCH_IMPRESSION_SHARE", :xml_name => "exactMatchImpressionShare", :type => :double },
31
+ { :request_name => "IMPRESSION_SHARE", :xml_name => "impressionShare", :type => :double },
32
+ { :request_name => "INVALID_CLICK_RATE", :xml_name => "invalidClickRate", :type => :double },
33
+ { :request_name => "INVIEW_CLICK_RATE", :xml_name => "viewableCtr", :type => :double },
34
+ { :request_name => "INVIEW_RATE", :xml_name => "viewableImpressionRate", :type => :double },
35
+ { :request_name => "QUALITY_LOST_IMPRESSION_SHARE", :xml_name => "qualityLostImpressionShare", :type => :double },
36
+ { :request_name => "REVENUE_CONVERSION_OLD", :xml_name => "revenueTotalConversionOld", :type => :double },
37
+ { :request_name => "TARGET_CPA", :xml_name => "targetCpa", :type => :double },
38
+ { :request_name => "TARGET_ROAS", :xml_name => "targetRoas", :type => :double },
39
+ { :request_name => "VALUE_PER_ALL_CONV", :xml_name => "valuePerAllConv", :type => :double },
40
+ { :request_name => "VALUE_PER_CONV", :xml_name => "valuePerConv", :type => :double },
41
+ { :request_name => "VIDEO_VIEWED_RATE", :xml_name => "videoViewedRate", :type => :double },
42
+ { :request_name => "ADGROUP_DISTRIBUTION_SETTINGS", :xml_name => "adgroupDistributionSettings", :type => :string },
43
+ { :request_name => "AD_DISTRIBUTION_SETTINGS", :xml_name => "adDistributionSettings", :type => :string },
44
+ { :request_name => "AD_EDITORIAL_STATUS", :xml_name => "adEditorialStatus", :type => :string },
45
+ { :request_name => "AD_TYPE", :xml_name => "adType", :type => :string },
46
+ { :request_name => "BID_AUTOMATION", :xml_name => "biddingAdjustmentMethodOfTargetPositionInSearchResults", :type => :string },
47
+ { :request_name => "BID_STRATEGY_TYPE", :xml_name => "autoBiddingType", :type => :string },
48
+ { :request_name => "CAMPAIGN_DISTRIBUTION_SETTINGS", :xml_name => "campaignDistributionSettings", :type => :string },
49
+ { :request_name => "CAMPAIGN_DISTRIBUTION_STATUS", :xml_name => "campaignDistributionStatus", :type => :string },
50
+ { :request_name => "CAMPAIGN_TYPE", :xml_name => "campaignType", :type => :string },
51
+ { :request_name => "CITY", :xml_name => "city", :type => :string },
52
+ { :request_name => "CITY_WARD_DISTRICT", :xml_name => "cityWardDistrict", :type => :string },
53
+ { :request_name => "CLICK_TYPE", :xml_name => "clickType", :type => :string },
54
+ { :request_name => "COUNTRY_TERRITORY", :xml_name => "countryTerritory", :type => :string },
55
+ { :request_name => "DAY_OF_WEEK", :xml_name => "dayOfWeek", :type => :string },
56
+ { :request_name => "DEVICE", :xml_name => "device", :type => :string },
57
+ { :request_name => "DEVICE_PREFERENCE", :xml_name => "focusDevice", :type => :string },
58
+ { :request_name => "EDITORIAL_STATUS", :xml_name => "editorialStatus", :type => :string },
59
+ { :request_name => "IS_SELF_ACTION", :xml_name => "isSelfAction", :type => :string },
60
+ { :request_name => "KEYWORD_DISTRIBUTION_SETTINGS", :xml_name => "keywordDistributionSettings", :type => :string },
61
+ { :request_name => "KEYWORD_EDITORIAL_STATUS", :xml_name => "kwEditorialStatus", :type => :string },
62
+ { :request_name => "KEYWORD_MATCH_TYPE", :xml_name => "keywordMatchType", :type => :string },
63
+ { :request_name => "KEYWORD_TARGETING_MATCH_TYPE", :xml_name => "targetKeywordMatchType", :type => :string },
64
+ { :request_name => "LIMITED_BUDGETS", :xml_name => "limitByCampaignBudgetOfTargetPositionInSearchResults", :type => :string },
65
+ { :request_name => "LOCATION_TYPE", :xml_name => "locationType", :type => :string },
66
+ { :request_name => "LOW_QUALITY_KEYWORDS", :xml_name => "lowQualityKeywordOfTargetPositionInSearchResults", :type => :string },
67
+ { :request_name => "MONTH_OF_YEAR", :xml_name => "monthofYear", :type => :string },
68
+ { :request_name => "NETWORK", :xml_name => "network", :type => :string },
69
+ { :request_name => "OBJECT_OF_CONVERSION_TRACKING", :xml_name => "objectiveOfConversionTracking", :type => :string },
70
+ { :request_name => "PLACEHOLDER_TYPE", :xml_name => "adDisplayOptionType", :type => :string },
71
+ { :request_name => "PREFECTURE", :xml_name => "prefecture", :type => :string },
72
+ { :request_name => "SEARCH_QUERY_MATCH_TYPE", :xml_name => "searchQueryMatchType", :type => :string },
73
+ { :request_name => "TARGET_LIST_ATTACHMENT_LEVEL", :xml_name => "targetListAttachmentLevel", :type => :string },
74
+ { :request_name => "TARGET_LIST_STATUS", :xml_name => "reachStatus", :type => :string },
75
+ { :request_name => "TARGET_LOCATION_RESTRICTION", :xml_name => "targetLocationRestriction", :type => :string },
76
+ { :request_name => "TARGET_SCHEDULE", :xml_name => "targetSchedule", :type => :string },
77
+ { :request_name => "TARGET_SEARCH_PAGE_LOCATION", :xml_name => "adPositionOfTargetPositionInSearchResults", :type => :string },
78
+ { :request_name => "ACCOUNT_ID", :xml_name => "accountID", :type => :string },
79
+ { :request_name => "ADGROUP_BID", :xml_name => "adGroupBid", :type => :long },
80
+ { :request_name => "ADGROUP_COUNT", :xml_name => "adGroups", :type => :long },
81
+ { :request_name => "ADGROUP_ID", :xml_name => "adgroupID", :type => :string },
82
+ { :request_name => "ADGROUP_TRACKING_ID", :xml_name => "adgroupTrackingID", :type => :string },
83
+ { :request_name => "AD_ID", :xml_name => "adID", :type => :string },
84
+ { :request_name => "AD_KEYWORD_ID", :xml_name => "adKeywordID", :type => :string },
85
+ { :request_name => "AD_TRACKING_ID", :xml_name => "adTrackingID", :type => :string },
86
+ { :request_name => "AUTO_VIDEO_PLAYS", :xml_name => "autoVideoPlays", :type => :long },
87
+ { :request_name => "BID", :xml_name => "bid", :type => :long },
88
+ { :request_name => "BID_MULTIPLIER", :xml_name => "bidAdjustment", :type => :long },
89
+ { :request_name => "BID_MULTIPLIER_OF_TARGET_PAGE_LOCATION", :xml_name => "biddingAdjustmentOfTargetPositionInSearchResults", :type => :long },
90
+ { :request_name => "BID_STRATEGY_ID", :xml_name => "autoBiddingID", :type => :string },
91
+ { :request_name => "CAMPAIGN_COUNT", :xml_name => "campaigns", :type => :long },
92
+ { :request_name => "CAMPAIGN_ID", :xml_name => "campaignID", :type => :string },
93
+ { :request_name => "CAMPAIGN_TRACKING_ID", :xml_name => "campaignTrackingID", :type => :string },
94
+ { :request_name => "CLICK", :xml_name => "clicks", :type => :long },
95
+ { :request_name => "CLICKS", :xml_name => "clicks", :type => :long },
96
+ { :request_name => "CLICK_VIDEO_PLAYS", :xml_name => "clickVideoPlays", :type => :long },
97
+ { :request_name => "CONVERSIONS", :xml_name => "conversions", :type => :long },
98
+ { :request_name => "CONVERSION_OLD", :xml_name => "totalConversionsOld", :type => :long },
99
+ { :request_name => "COST", :xml_name => "cost", :type => :long },
100
+ { :request_name => "DAILY_SPENDING_LIMIT", :xml_name => "dailySpendingLimit", :type => :long },
101
+ { :request_name => "FEED_ID", :xml_name => "dataAssignmentListId", :type => :string },
102
+ { :request_name => "FEED_ID", :xml_name => "feedID", :type => :string },
103
+ { :request_name => "FEED_ITEM_ID", :xml_name => "adDisplayOptionID", :type => :string },
104
+ { :request_name => "FEED_ITEM_ID", :xml_name => "dataAssignmentListDetails", :type => :string },
105
+ { :request_name => "FEED_ITEM_TRACKING_ID", :xml_name => "adDisplayOptionTrackingID", :type => :string },
106
+ { :request_name => "FIRST_PAGE_BID_ESTIMATE", :xml_name => "firstPageBidEstimate", :type => :long },
107
+ { :request_name => "HOUR", :xml_name => "hourofday", :type => :long },
108
+ { :request_name => "HOUR_OF_DAY", :xml_name => "hourofday", :type => :long },
109
+ { :request_name => "IMPS", :xml_name => "impressions", :type => :long },
110
+ { :request_name => "INVALID_CLICKS", :xml_name => "invalidClicks", :type => :long },
111
+ { :request_name => "INVIEW_CLICK", :xml_name => "viewableClicks", :type => :long },
112
+ { :request_name => "KEYWORD_ID", :xml_name => "keywordID", :type => :string },
113
+ { :request_name => "KEYWORD_TRACKING_ID", :xml_name => "keywordTrackingID", :type => :string },
114
+ { :request_name => "LOWER_BID_LIMIT_OF_TARGET_CPA", :xml_name => "lowerBidLimitForTargetCpa", :type => :long },
115
+ { :request_name => "LOWER_BID_LIMIT_OF_TARGET_ROAS", :xml_name => "lowerBidLimitForTargetRoas", :type => :long },
116
+ { :request_name => "QUALITY_INDEX", :xml_name => "qualityIndex", :type => :long },
117
+ { :request_name => "REVENUE", :xml_name => "revenue", :type => :long },
118
+ { :request_name => "REVENUE_OLD", :xml_name => "totalRevenueOld", :type => :long },
119
+ { :request_name => "REVENUE_PER_CONV", :xml_name => "revenuePerConv", :type => :long },
120
+ { :request_name => "SEARCHKEYWORD_ID", :xml_name => "searchKeywordID", :type => :string },
121
+ { :request_name => "TARGETING_ADGROUP_ID", :xml_name => "targetAdGroupID", :type => :string },
122
+ { :request_name => "TARGETING_CAMPAIGN_ID", :xml_name => "targetCampaignID", :type => :string },
123
+ { :request_name => "TARGET_LIST_ID", :xml_name => "targetListID", :type => :string },
124
+ { :request_name => "TARGET_LIST_TRACKING_ID", :xml_name => "targetListTrackingID", :type => :string },
125
+ { :request_name => "TARGET_SCHEDULE_ID", :xml_name => "targetScheduleID", :type => :string },
126
+ { :request_name => "TOP_OF_PAGE_BID_ESTIMATE", :xml_name => "topOfPageBidEstimate", :type => :long },
127
+ { :request_name => "TOTAL_VIEWABLE_IMPS", :xml_name => "measurableImpressions", :type => :long },
128
+ { :request_name => "UNIQUE_USERS", :xml_name => "uniqueUsers", :type => :long },
129
+ { :request_name => "UPPER_BID_LIMIT_OF_MAXIMIZE_CLICKS", :xml_name => "bidLimitForMaximizeClicks", :type => :long },
130
+ { :request_name => "UPPER_BID_LIMIT_OF_TARGET_CPA", :xml_name => "bidLimitForTargetCpa", :type => :long },
131
+ { :request_name => "UPPER_BID_LIMIT_OF_TARGET_PAGE_LOCATION", :xml_name => "bidLimitForTargetPositionInSearchResults", :type => :long },
132
+ { :request_name => "UPPER_BID_LIMIT_OF_TARGET_ROAS", :xml_name => "bidLimitForTargetRoas", :type => :long },
133
+ { :request_name => "URL_ID", :xml_name => "destinationURLID", :type => :string },
134
+ { :request_name => "VIDEO_PLAYS", :xml_name => "videoPlays", :type => :long },
135
+ { :request_name => "VIDEO_VIEWS_TO_100", :xml_name => "videoViewsTo100", :type => :long },
136
+ { :request_name => "VIDEO_VIEWS_TO_25", :xml_name => "videoViewsTo25", :type => :long },
137
+ { :request_name => "VIDEO_VIEWS_TO_50", :xml_name => "videoViewsTo50", :type => :long },
138
+ { :request_name => "VIDEO_VIEWS_TO_75", :xml_name => "videoViewsTo75", :type => :long },
139
+ { :request_name => "VIDEO_VIEWS_TO_95", :xml_name => "videoViewsTo95", :type => :long },
140
+ { :request_name => "VIEWABLE_IMPS", :xml_name => "viewableImpressions", :type => :long },
141
+ { :request_name => "ACCOUNT_NAME", :xml_name => "accountName", :type => :string },
142
+ { :request_name => "ADGROUP_NAME", :xml_name => "adgroupName", :type => :string },
143
+ { :request_name => "AD_LAYOUT", :xml_name => "adLayout", :type => :string },
144
+ { :request_name => "AD_NAME", :xml_name => "adName", :type => :string },
145
+ { :request_name => "AD_STYLE", :xml_name => "adStyle", :type => :string },
146
+ { :request_name => "AD_TITLE", :xml_name => "title", :type => :string },
147
+ { :request_name => "AD_TYPE", :xml_name => "adType", :type => :string },
148
+ { :request_name => "AGE", :xml_name => "age", :type => :string },
149
+ { :request_name => "APPLI", :xml_name => "appli", :type => :string },
150
+ { :request_name => "APP_ID", :xml_name => "appID", :type => :string },
151
+ { :request_name => "APP_NAME", :xml_name => "appName", :type => :string },
152
+ { :request_name => "APP_OS", :xml_name => "appOS", :type => :string },
153
+ { :request_name => "BID_STRATEGY_NAME", :xml_name => "autoBiddingName", :type => :string },
154
+ { :request_name => "CALLOUT", :xml_name => "callout", :type => :string },
155
+ { :request_name => "CAMPAIGN_END_DATE", :xml_name => "campaignEndDate", :type => :string },
156
+ { :request_name => "CAMPAIGN_NAME", :xml_name => "campaignName", :type => :string },
157
+ { :request_name => "CAMPAIGN_START_DATE", :xml_name => "campaignStartDate", :type => :string },
158
+ { :request_name => "CAMPAIGN_TYPE", :xml_name => "campaignType", :type => :string },
159
+ { :request_name => "CARRIER", :xml_name => "carrier", :type => :string },
160
+ { :request_name => "CITY_ID", :xml_name => "cityID", :type => :string },
161
+ { :request_name => "CITY_NAME", :xml_name => "city", :type => :string },
162
+ { :request_name => "CONVERSION_CATEGORY", :xml_name => "objectiveOfConversionTracking", :type => :string },
163
+ { :request_name => "CONVERSION_LABEL", :xml_name => "conversionName", :type => :string },
164
+ { :request_name => "CONVERSION_NAME", :xml_name => "conversionName", :type => :string },
165
+ { :request_name => "CUSTOM_PARAMETERS", :xml_name => "customParameters", :type => :string },
166
+ { :request_name => "CUSTOM_URL", :xml_name => "customURL", :type => :string },
167
+ { :request_name => "DAY", :xml_name => "day", :type => :string },
168
+ { :request_name => "DELIVER", :xml_name => "deliverName", :type => :string },
169
+ { :request_name => "DELIVER_URL", :xml_name => "adDeliveryURL", :type => :string },
170
+ { :request_name => "DESC", :xml_name => "description", :type => :string },
171
+ { :request_name => "DESCRIPTION", :xml_name => "description1", :type => :string },
172
+ { :request_name => "DESCRIPTION1", :xml_name => "description1", :type => :string },
173
+ { :request_name => "DESCRIPTION2", :xml_name => "description2", :type => :string },
174
+ { :request_name => "DESTINATION_URL", :xml_name => "destinationURL", :type => :string },
175
+ { :request_name => "DEVICE", :xml_name => "device", :type => :string },
176
+ { :request_name => "DIRECTORY1", :xml_name => "directory1", :type => :string },
177
+ { :request_name => "DIRECTORY2", :xml_name => "directory2", :type => :string },
178
+ { :request_name => "DISPLAY_URL", :xml_name => "displayURL", :type => :string },
179
+ { :request_name => "FEED_ITEM_ATTRIBUTES", :xml_name => "dataAssignmentList", :type => :string },
180
+ { :request_name => "FEED_ITEM_END_DATE", :xml_name => "adDisplayOptionEndDate", :type => :string },
181
+ { :request_name => "FEED_ITEM_END_DATE", :xml_name => "dataAssignmentListDetailsEndDate", :type => :string },
182
+ { :request_name => "FEED_ITEM_START_DATE", :xml_name => "adDisplayOptionStartDate", :type => :string },
183
+ { :request_name => "FEED_ITEM_START_DATE", :xml_name => "dataAssignmentListDetailsStartDate", :type => :string },
184
+ { :request_name => "FREQUENCY", :xml_name => "frequency", :type => :string },
185
+ { :request_name => "GENDER", :xml_name => "gender", :type => :string },
186
+ { :request_name => "IMAGE_OPTION", :xml_name => "imageOption", :type => :string },
187
+ { :request_name => "INTEREST_CATEGORY", :xml_name => "interestCategory", :type => :string },
188
+ { :request_name => "KEYWORD", :xml_name => "keyword", :type => :string },
189
+ { :request_name => "KEYWORD_TARGETING_TEXT", :xml_name => "targetKeywordText", :type => :string },
190
+ { :request_name => "LANDING_PAGE_URL", :xml_name => "landingPageURL", :type => :string },
191
+ { :request_name => "LANDING_PAGE_URL_SMARTPHONE", :xml_name => "landingPageURLSmartphone", :type => :string },
192
+ { :request_name => "MEDIA_AD_FORMAT", :xml_name => "pixelSize", :type => :string },
193
+ { :request_name => "MEDIA_FILE_NAME", :xml_name => "fileName", :type => :string },
194
+ { :request_name => "MEDIA_ID", :xml_name => "mediaID", :type => :string },
195
+ { :request_name => "MEDIA_NAME", :xml_name => "mediaName", :type => :string },
196
+ { :request_name => "MONTH", :xml_name => "month", :type => :string },
197
+ { :request_name => "NEGATIVE_KEYWORD", :xml_name => "negativeKeywords", :type => :string },
198
+ { :request_name => "OS", :xml_name => "os", :type => :string },
199
+ { :request_name => "PHONE_NUMBER", :xml_name => "phoneNumber", :type => :string },
200
+ { :request_name => "PREF_ID", :xml_name => "prefectureID", :type => :string },
201
+ { :request_name => "PREF_NAME", :xml_name => "prefecture", :type => :string },
202
+ { :request_name => "QUARTER", :xml_name => "quarter", :type => :string },
203
+ { :request_name => "QUICK_LINK_TEXT", :xml_name => "quickLinkText", :type => :string },
204
+ { :request_name => "QUICK_LINK_URL", :xml_name => "quickLinkURL", :type => :string },
205
+ { :request_name => "SEARCHKEYWORD", :xml_name => "searchKeyword", :type => :string },
206
+ { :request_name => "SEARCH_QUERY", :xml_name => "searchQuery", :type => :string },
207
+ { :request_name => "SEARCH_QUERY_DESTINATION_URL", :xml_name => "searchQueryDestinationURL", :type => :string },
208
+ { :request_name => "SITE_CATEGORY", :xml_name => "siteCategory", :type => :string },
209
+ { :request_name => "TARGET_LIST_NAME", :xml_name => "targetListName", :type => :string },
210
+ { :request_name => "TARGET_LOCATION_ID", :xml_name => "targetLocationID", :type => :string },
211
+ { :request_name => "TARGET_LOCATION_NAME", :xml_name => "targetLocation", :type => :string },
212
+ { :request_name => "TARGET_LOCATION_NAME", :xml_name => "targetLocationName", :type => :string },
213
+ { :request_name => "TITLE", :xml_name => "title", :type => :string },
214
+ { :request_name => "TITLE1", :xml_name => "title1", :type => :string },
215
+ { :request_name => "TITLE2", :xml_name => "title2", :type => :string },
216
+ { :request_name => "TRACKING_URL", :xml_name => "trackingURL", :type => :string },
217
+ { :request_name => "URL_NAME", :xml_name => "destinationURL", :type => :string },
218
+ { :request_name => "WARD_ID", :xml_name => "wardID", :type => :string },
219
+ { :request_name => "WARD_NAME", :xml_name => "ward", :type => :string },
220
+ { :request_name => "WEEK", :xml_name => "week", :type => :string },
221
+ { :request_name => "YEAR", :xml_name => "year", :type => :string },
222
+ ]
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,9 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ class InvalidEnumError < StandardError
5
+ end
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,36 @@
1
+ require "savon"
2
+ module Embulk
3
+ module Input
4
+ module YahooAds
5
+ class LocationService < ::Savon::Client
6
+ def invoke
7
+ return @response unless @response.nil?
8
+ ::Embulk.logger.info "SOAP Request: #{self.wsdl.document}"
9
+ @response ||= self.call(:get, message: {
10
+ account_id: @account_id,
11
+ }).body[:get_response][:rval][:value].to_s
12
+ end
13
+
14
+ def self.build(account_id, auth_config)
15
+ service = self.new({
16
+ wsdl: "https://#{auth_config.location}/services/#{auth_config.version}/LocationService?wsdl",
17
+ namespace: auth_config.namespace,
18
+ soap_header: {
19
+ "tns:RequestHeader": {
20
+ "tns:license" => auth_config.license,
21
+ "tns:apiAccountId" => auth_config.api_account,
22
+ "tns:apiAccountPassword" => auth_config.api_password,
23
+ }
24
+ },
25
+ })
26
+ service.account_id = account_id
27
+ service
28
+ end
29
+
30
+ def account_id=(val)
31
+ @account_id = val
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,74 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ class Plugin < InputPlugin
5
+ ::Embulk::Plugin.register_input("yahoo_ads", self)
6
+
7
+ def self.transaction(config, &control)
8
+ # configuration code:
9
+ task = {
10
+ :location => config.param("location", :string),
11
+ :version => config.param("version", :string),
12
+ :license => config.param("license", :string),
13
+ :api_account => config.param("api_account", :string),
14
+ :api_password => config.param("api_password", :string),
15
+ :namespace => config.param("namespace", :string),
16
+ :columns => config.param("columns", :array),
17
+ :account_id => config.param("account_id", :string),
18
+ :report_type => config.param("report_type", :string),
19
+ :date_range => {
20
+ :min => config.param("date_range_min", :string),
21
+ :max => config.param("date_range_max", :string),
22
+ },
23
+ }
24
+
25
+ columns = task[:columns].map do |colname|
26
+ column = Column.all.find{|c| c[:request_name] == colname}
27
+ ::Embulk::Column.new(nil, colname, column[:type])
28
+ end
29
+
30
+ resume(task, columns, 1, &control)
31
+ end
32
+
33
+ def self.resume(task, columns, count, &control)
34
+ task_reports = yield(task, columns, count)
35
+
36
+ next_config_diff = {}
37
+ return next_config_diff
38
+ end
39
+
40
+ def init
41
+ end
42
+
43
+ def run
44
+ auth_config = AuthConfig.new({
45
+ :location => task["location"],
46
+ :version => task["version"],
47
+ :license => task["license"],
48
+ :api_account => task["api_account"],
49
+ :api_password => task["api_password"],
50
+ :namespace => task["namespace"],
51
+ })
52
+ ReportClient.new(task["account_id"], auth_config).run({
53
+ :report_type => task["report_type"],
54
+ :date_range_type => 'CUSTOM_DATE',
55
+ :date_range => {
56
+ :start_date => task["date_range"]["min"],
57
+ :end_date => task["date_range"]["max"],
58
+ },
59
+ :fields => task["columns"]
60
+ }).each do |row|
61
+ page_builder.add(task["columns"].map do|column|
62
+ col = Column.all.find{|c| c[:request_name] == column}
63
+ row.send(col[:xml_name])
64
+ end)
65
+ end
66
+ page_builder.finish
67
+
68
+ task_report = {}
69
+ return task_report
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,126 @@
1
+ require "nokogiri"
2
+ require "open-uri"
3
+ require "ostruct"
4
+ module Embulk
5
+ module Input
6
+ module YahooAds
7
+ class ReportClient < Client
8
+ def run(query)
9
+ report_id = query_report_definition(query)
10
+ ::Embulk.logger.info "Create Report, report_id = #{report_id}"
11
+ report_job_id = query_report_job(report_id)
12
+ ::Embulk.logger.info "Create Report JOB, report_job_id = #{report_job_id}"
13
+ download_url = report_download_url(report_job_id)
14
+ ::Embulk.logger.info "Download Report, URL = #{download_url}"
15
+ xml = xml_parse(download_url)
16
+ remove_report_job(report_job_id)
17
+ ::Embulk.logger.info "Remove Report JOB, report_job_id = #{report_job_id}"
18
+ remove_report_definition(report_id)
19
+ ::Embulk.logger.info "Remove Report, report_id = #{report_id}"
20
+ xml
21
+ end
22
+
23
+ private
24
+ def query_report_definition(selector)
25
+ response = self.invoke(:ReportDefinitionService, :mutate, message: {
26
+ :operations => {
27
+ :operator => 'ADD',
28
+ :account_id => @account_id,
29
+ :operand => {
30
+ :account_id => @account_id,
31
+ :report_name => "YahooReport_#{DateTime.now.strftime("%Y%m%d_%H%I%s")}",
32
+ :report_type => nil,
33
+ :fields => [],
34
+ :compress => 'NONE',
35
+ :is_template => 'FALSE',
36
+ :interval_type => 'ONETIME',
37
+ :format => 'XML',
38
+ :language => 'JA',
39
+ :include_zero_impressions => 'FALSE',
40
+ :include_deleted => 'TRUE',
41
+ }.deep_merge(selector)
42
+ }
43
+ })
44
+ if response[:mutate_response][:rval][:values][:operation_succeeded] == false
45
+ error = response[:mutate_response][:rval][:values][:error]
46
+ raise ::Embulk::Input::YahooAds::Error::InvalidEnumError, error.to_json
47
+ end
48
+ response[:mutate_response][:rval][:values][:report_definition][:report_id].to_s
49
+ end
50
+
51
+ def query_report_job(report_id)
52
+ response = self.invoke(:ReportService, :mutate, message: {
53
+ :operations => {
54
+ :operator => 'ADD',
55
+ :account_id => @account_id,
56
+ :operand => {
57
+ :report_id => report_id
58
+ }
59
+ }
60
+ })
61
+ response[:mutate_response][:rval][:values][:report_record][:report_job_id].to_s
62
+ end
63
+
64
+ def report_download_url(report_job_id, wait_second = 5)
65
+ sleep(wait_second)
66
+ response = self.invoke(:ReportService, :get, message: {
67
+ :selector => {
68
+ :account_id => @account_id,
69
+ :report_job_ids => [report_job_id]
70
+ }
71
+ })
72
+ status = nil
73
+ if response[:get_response][:rval][:values][:report_record][:status].nil? == false
74
+ status = response[:get_response][:rval][:values][:report_record][:status].to_s
75
+ elsif response[:get_response][:rval][:values][:report_record][:report_job_status].nil? == false
76
+ status = response[:get_response][:rval][:values][:report_record][:report_job_status].to_s
77
+ end
78
+ case status
79
+ when 'COMPLETED' then
80
+ return response[:get_response][:rval][:values][:report_record][:report_download_url].to_s
81
+ when 'IN_PROGRESS' then
82
+ return report_download_url(report_job_id, wait_second * 2)
83
+ when 'WAIT' then
84
+ return report_download_url(report_job_id, wait_second * 2)
85
+ end
86
+ end
87
+
88
+ def xml_parse(url)
89
+ xml = Nokogiri::XML(open(url).read)
90
+ columns = xml.css('column').map{|column| column.attribute('name').value }
91
+ xml.css('row').map do |row|
92
+ value = {}
93
+ columns.each do |column|
94
+ value[column.to_sym] = row.attribute(column).value
95
+ end
96
+ OpenStruct.new(value)
97
+ end
98
+ end
99
+
100
+ def remove_report_job(report_job_id)
101
+ self.invoke(:ReportService, :mutate, message: {
102
+ :operations => {
103
+ :operator => 'REMOVE',
104
+ :accountId => @account_id,
105
+ :operand => {
106
+ :report_job_id => report_job_id
107
+ }
108
+ }
109
+ })
110
+ end
111
+
112
+ def remove_report_definition(report_id)
113
+ self.invoke(:ReportDefinitionService, :mutate, message: {
114
+ :operations => {
115
+ :operator => 'REMOVE',
116
+ :account_id => @account_id,
117
+ :operand => {
118
+ :report_id => report_id
119
+ }
120
+ }
121
+ })
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,7 @@
1
+ module Embulk
2
+ module Input
3
+ module YahooAds
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: embulk-input-yahoo_ads
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ryota.yamada
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ name: savon
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 1.8.1
33
+ name: nokogiri
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.1
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.8.30
47
+ name: embulk
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.30
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.10.6
61
+ name: bundler
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.10.6
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ name: rake
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ description: Loads records from Yahoo Ads.
84
+ email:
85
+ - ryota.yamada@principle-c.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".ruby-version"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - embulk-input-yahoo_ads.gemspec
97
+ - example/display_ads.yml
98
+ - lib/embulk/input/yahoo_ads.rb
99
+ - lib/embulk/input/yahoo_ads/auth_config.rb
100
+ - lib/embulk/input/yahoo_ads/client.rb
101
+ - lib/embulk/input/yahoo_ads/column.rb
102
+ - lib/embulk/input/yahoo_ads/error/invalid_enum_error.rb
103
+ - lib/embulk/input/yahoo_ads/location_service.rb
104
+ - lib/embulk/input/yahoo_ads/plugin.rb
105
+ - lib/embulk/input/yahoo_ads/report_client.rb
106
+ - lib/embulk/input/yahoo_ads/version.rb
107
+ homepage: https://github.com/principle-c/embulk-input-yahoo_ads
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.6.6
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Yahoo Ads input plugin for Embulk
131
+ test_files: []