embulk-input-yahoo_ads 0.1.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.
@@ -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: []