Skip to content

Instantly share code, notes, and snippets.

@klmansel
Last active September 9, 2019 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klmansel/090541647b135417510af237fd70f3d1 to your computer and use it in GitHub Desktop.
Save klmansel/090541647b135417510af237fd70f3d1 to your computer and use it in GitHub Desktop.
ApiMetrics module created to track Google Ads API calls
class AdwordsApiService::AdGroupGateway < AdwordsApiService::Base
def find(ad_group_id)
selector = {
fields: ad_group_fields,
predicates: [
{
field: "Id",
operator: "EQUALS",
values: [ad_group_id]
}
]
}
begin
response = api_service.get(selector)
if response[:total_num_entries] > 0
AdGroupSerializer.deserialize(response[:entries].first)
else
raise AdwordsApiService::Error, "Ad Group not found"
end
rescue TypeError
raise AdwordsApiService::Error, "Ad Group not found"
end
end
def find_by_campaign_id(campaign_id)
selector = {
fields: ad_group_fields,
predicates: [
{
field: "CampaignId",
operator: "EQUALS",
values: [campaign_id]
}
]
}
begin
response = api_service.get(selector)
if response && response[:entries]
AdGroupSerializer.deserialize(response[:entries])
else
[]
end
rescue AdwordsApi::Errors::ApiException => error
raise AdwordsApiService::Error, error.message
end
end
def create(ad_group)
serialized_ad_group = AdGroupSerializer.serialize(ad_group)
operation = {
operator: "ADD",
operand: serialized_ad_group
}
mutate(operation)
end
def update(ad_group)
serialized_ad_group = AdGroupSerializer.serialize(ad_group)
operation = {
operator: "SET",
operand: serialized_ad_group
}
mutate(operation)
end
def link_audience_to_ad_group(ad_group_id, audience_id)
operation = {
operator: "ADD",
operand: {
xsi_type: "BiddableAdGroupCriterion",
ad_group_id: ad_group_id,
criterion: {
xsi_type: "CriterionUserList",
user_list_id: audience_id
}
}
}
begin
response = @api_service ||= configure_api_service(:AdGroupCriterionService).mutate([operation])
response[:value].first
rescue AdwordsApi::Errors::ApiException => error
raise AdwordsApiService::Error, error.message
rescue AdsCommon::Errors::UnexpectedParametersError
raise AdwordsApiService::Error, "Invalid request"
end
end
private
def mutate(operation)
response = api_service.mutate([operation])
response[:value].first
rescue AdwordsApi::Errors::ApiException => error
raise AdwordsApiService::Error, error.message
end
def api_service
@api_service ||= configure_api_service(:AdGroupService)
end
def ad_group_fields
[
"Id", "Name", "Status", "CampaignId", "BiddingStrategySource", "CpcBid", "CpmBid"
]
end
end
class Admin::ApiCallsController < AdminController
def index
@api_calls = policy_scope(ApiCall).where("created_at > ?", 30.days.ago)
@daily_calls = @api_calls.group_by_day(:created_at).count
@weekly_calls = @api_calls.group_by_week(:created_at, time_zone: "Eastern Time (US & Canada)").count
@last_hour_calls = policy_scope(ApiCall).where("created_at > ?", 1.hour.ago).count
end
end
# services/adwords_api_service/base.rb
class AdwordsApiService::Base
# The ApiMetrics module creates an ApiCall record for each
# get and mutate operation. This module must prepend an AdwordsApi::Api
# instance and is used in gateways by chaining 'class.prepend ApiMetrics'
# to API service instantiation
# @author [karamansel]
module ApiMetrics
RECORDED_METHODS = [:mutate, :get].freeze
RECORDED_METHODS.each do |method|
define_method method do |*args|
super(*args) do |header|
header[:operations].times do
ApiCall.create!(
service_name: header[:service_name],
method_name: header[:method_name]
)
end
end
end
end
end
include CustomExceptions
API_VERSION = :v201809
def initialize(oauth2_token, client_customer_id = nil)
# unrelated code removed
end
# The only Adwords endpoint that does not require a customer's Adwords Customer ID
# Used when they Oauth with our application to fetch their Customer ID.
def ads_accounts
# unrelated code removed
end
private
def authentication_headers
# unrelated code removed
end
# log level options in order of least to most logging:
# FATAL, ERROR, WARN, INFO, DEBUG
def environment_based_log_level
# unrelated code removed
end
protected
def configure_api_service(service_name)
service = @adwords.service(service_name)
service.class.prepend ApiMetrics unless Rails.env.development?
service
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment