Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| # frozen_string_literal: true | |
| # Copyright (C) 2015 Twitter, Inc. | |
| require 'zlib' | |
| require 'open-uri' | |
| module TwitterAds | |
| module Analytics | |
| ANALYTICS_MAP = { | |
| 'TwitterAds::Campaign' => 'CAMPAIGN'.freeze, | |
| 'TwitterAds::LineItem' => 'LINE_ITEM'.freeze, | |
| 'TwitterAds::OrganicTweet' => 'ORGANIC_TWEET'.freeze, | |
| 'TwitterAds::Creative::PromotedAccount' => 'ACCOUNT'.freeze, | |
| 'TwitterAds::Creative::PromotedTweet' => 'PROMOTED_TWEET'.freeze | |
| }.freeze | |
| def self.included(klass) | |
| klass.send :include, InstanceMethods | |
| klass.extend ClassMethods | |
| end | |
| module InstanceMethods | |
| # Pulls a list of metrics for the current object instance. | |
| # | |
| # @example | |
| # metric_groups = [:promoted_tweet_timeline_clicks, :promoted_tweet_search_clicks] | |
| # object.stats(metrics) | |
| # | |
| # @param metric_groups [Array] A collection of metric groups to fetch. | |
| # @param opts [Hash] An optional Hash of extended options. | |
| # @option opts [Time] :start_time The starting time to use (default: 7 days ago). | |
| # @option opts [Time] :end_time The end time to use (default: now). | |
| # @option opts [Symbol] :granularity The granularity to use (default: :hour). | |
| # | |
| # @return [Array] The collection of stats requested. | |
| # | |
| # @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation | |
| # @since 1.0.0 | |
| def stats(metric_groups, opts = {}) | |
| self.class.stats(account, [id], metric_groups, opts) | |
| end | |
| end | |
| module ClassMethods | |
| # Pulls a list of metrics for a specified set of object IDs. | |
| # | |
| # @example | |
| # ids = ['7o4em', 'oc9ce', '1c5lji'] | |
| # metric_groups = [MetricGroups.MOBILE_CONVERSION, MetricGroups.ENGAGEMENT] | |
| # object.stats(account, ids, metric_groups) | |
| # | |
| # @param account [Account] The Account object instance. | |
| # @param ids [Array] A collection of object IDs being targeted. | |
| # @param metric_groups [Array] A collection of metric_groups to be fetched. | |
| # @param opts [Hash] An optional Hash of extended options. | |
| # @option opts [Time] :start_time The starting time to use (default: 7 days ago). | |
| # @option opts [Time] :end_time The end time to use (default: now). | |
| # @option opts [Symbol] :granularity The granularity to use (default: :hour). | |
| # @option opts [Symbol] :placement The placement of entity (default: ALL_ON_TWITTER). | |
| # | |
| # @return [Array] The collection of stats requested. | |
| # | |
| # @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation | |
| # @since 1.0.0 | |
| def stats(account, ids, metric_groups, opts = {}) | |
| # set default metric values | |
| end_time = opts.fetch(:end_time, (Time.now - Time.now.sec - (60 * Time.now.min))) | |
| start_time = opts.fetch(:start_time, end_time - 604_800) # 7 days ago | |
| granularity = opts.fetch(:granularity, :hour) | |
| start_utc_offset = opts[:start_utc_offset] || opts[:utc_offset] | |
| end_utc_offset = opts[:end_utc_offset] || opts[:utc_offset] | |
| placement = opts.fetch(:placement, Placement::ALL_ON_TWITTER) | |
| params = { | |
| metric_groups: metric_groups.join(','), | |
| start_time: TwitterAds::Utils.to_time(start_time, granularity, start_utc_offset), | |
| end_time: TwitterAds::Utils.to_time(end_time, granularity, end_utc_offset), | |
| granularity: granularity.to_s.upcase, | |
| entity: ANALYTICS_MAP[name], | |
| placement: placement | |
| } | |
| params['entity_ids'] = ids.join(',') | |
| resource = self::RESOURCE_STATS % { account_id: account.id } | |
| response = Request.new(account.client, :get, resource, params: params).perform | |
| response.body[:data] | |
| end | |
| # Create an asynchronous analytics job for a given ads account. | |
| # A job_id is returned, which you can use to poll the | |
| # GET stats/jobs/accounts/:account_id endpoint, checking until the job is successful. | |
| # | |
| # @example | |
| # ids = ['7o4em', 'oc9ce', '1c5lji'] | |
| # metric_groups = [MetricGroups.MOBILE_CONVERSION, MetricGroups.ENGAGEMENT] | |
| # object.create_async_job(account, ids, metric_groups) | |
| # | |
| # @param account [Account] The Account object instance. | |
| # @param ids [Array] A collection of object IDs being targeted. | |
| # @param metric_groups [Array] A collection of metric_groups to be fetched. | |
| # @param opts [Hash] An optional Hash of extended options. | |
| # @option opts [Time] :start_time The starting time to use (default: 7 days ago). | |
| # @option opts [Time] :end_time The end time to use (default: now). | |
| # @option opts [Symbol] :granularity The granularity to use (default: :hour). | |
| # @option opts [Symbol] :placement The placement of entity (default: ALL_ON_TWITTER). | |
| # @option opts [Symbol] :segmentation_type The segmentation type to use (default: none). | |
| # | |
| # @return The response of creating job | |
| # | |
| # @see https://dev.twitter.com/ads/analytics/metrics-and-segmentation | |
| # @sync 1.0.0 | |
| def create_async_job(account, ids, metric_groups, opts = {}) | |
| # set default metric values | |
| end_time = opts.fetch(:end_time, (Time.now - Time.now.sec - (60 * Time.now.min))) | |
| start_time = opts.fetch(:start_time, end_time - 604_800) # 7 days ago | |
| granularity = opts.fetch(:granularity, :hour) | |
| start_utc_offset = opts[:start_utc_offset] || opts[:utc_offset] | |
| end_utc_offset = opts[:end_utc_offset] || opts[:utc_offset] | |
| placement = opts.fetch(:placement, Placement::ALL_ON_TWITTER) | |
| segmentation_type = opts.fetch(:segmentation_type, nil) | |
| country = opts.fetch(:country, nil) | |
| platform = opts.fetch(:platform, nil) | |
| params = { | |
| metric_groups: metric_groups.join(','), | |
| start_time: TwitterAds::Utils.to_time(start_time, granularity, start_utc_offset), | |
| end_time: TwitterAds::Utils.to_time(end_time, granularity, end_utc_offset), | |
| granularity: granularity.to_s.upcase, | |
| entity: ANALYTICS_MAP[name], | |
| placement: placement, | |
| country: country, | |
| platform: platform | |
| }.compact | |
| params[:segmentation_type] = segmentation_type.to_s.upcase if segmentation_type | |
| params['entity_ids'] = ids.join(',') | |
| resource = self::RESOURCE_ASYNC_STATS % { account_id: account.id } | |
| puts 'my resource is ' + resource | |
| response = Request.new(account.client, :post, resource, params: params).perform | |
| response.body[:data] | |
| end | |
| # Check async job status. | |
| # GET /#{TwitterAds::API_VERSION}/stats/jobs/accounts/:account_id | |
| # | |
| # @example | |
| # TwitterAds::LineItem.check_async_job_status(account, job_id: '1357343438724431305') | |
| # | |
| # @param account [Account] The Account object instance. | |
| # @option opts [String] :job_id The starting time to use (default: 7 days ago). | |
| # | |
| # @return A cursor of job statuses | |
| def check_async_job_status(account, opts = {}) | |
| # set default values | |
| job_ids = opts.fetch(:job_ids, nil) | |
| params = {} | |
| params[:job_ids] = Array.wrap(job_ids).join(',') if job_ids | |
| resource = self::RESOURCE_ASYNC_STATS % { account_id: account.id } | |
| request = Request.new(account.client, :get, resource, params: params) | |
| Cursor.new(nil, request, init_with: [account]) | |
| end | |
| # Fetch async job data for a completed job. | |
| # Raises HTTP 404 exception, otherwise retries up to 5 times with exponential backoff. | |
| # | |
| # @example | |
| # response_data = TwitterAds::LineItem.fetch_async_job_data(account, file_url) | |
| # | |
| # @param data_url [String] The URL from the successful completion of an async job. | |
| # | |
| # @return A cursor of job statuses | |
| def fetch_async_job_data(data_url) | |
| tries = 0 | |
| begin | |
| tries += 1 | |
| raw_file = open(data_url) | |
| unzipped_file = Zlib::GzipReader.new(raw_file) | |
| response_data = unzipped_file.read | |
| response = JSON.parse(response_data) | |
| response['data'] | |
| rescue OpenURI::HTTPError => e | |
| unless e.io.status[0] == '404' | |
| if tries < 5 | |
| sleep(2**tries) | |
| retry | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end |