def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if not self.request.user.has_adwords_account: return context context['has_adwords_account'] = True adapter = Adapter(self.request.user) data = adapter.get_mapped_keywords(self.object) order_by = self.request.GET.get('sort', 'keyword') try: page = int(self.request.GET.get('page', 1)) except ValueError: # raise a 400 raise SuspiciousOperation( 'Bad request: GET parameter `page` is not an integer') table = KeywordTable(data, order_by=order_by) table.paginate(page=page, per_page=20) context.update({ 'keywords': table, }) return context
def get(self, request, *args, **kwargs): adapter = Adapter(self.request.user) monthly_spend = adapter.get_monthly_spend() quote = Quote(monthly_adwords_spend=monthly_spend) quote.set_user_details(request.user, commit=False) quote.calculate_quote(commit=False) quote.set_type_automatic(commit=False) quote.save() request.session['quote_pk'] = quote.pk return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if not self.request.user.has_adwords_account: return context context['has_adwords_account'] = True date_range_form = DateRangeForm() date_from = date_range_form.fields['date_from'].initial() date_to = date_range_form.fields['date_to'].initial() should_aggregate = date_range_form.fields['should_aggregate'].initial if 'date_from' in self.request.GET and 'date_to' in self.request.GET: date_range_form = DateRangeForm(self.request.GET.copy()) if date_range_form.is_valid(): date_from = date_range_form.cleaned_data['date_from'] date_to = date_range_form.cleaned_data['date_to'] should_aggregate = date_range_form.cleaned_data[ 'should_aggregate'] context['date_range_form'] = date_range_form context['chart_range'] = self.request.GET.get('chart_range', 'thisWeek') adapter = Adapter(self.request.user) kwargs = { 'cast_dates': False, 'campaign_id': self.object.adwords_campaign_id } if context['chart_range'] != 'allTime': kwargs['date_range'] = adapter.format_date_range( date_from, date_to) metrics = adapter.get_campaign_metrics(**kwargs) if should_aggregate: metrics = adapter.aggregate_campaign_metrics_to_monthly( metrics, date_format='%Y-%m-%d') for metric in metrics.values(): metric['cpc'] /= 10**6 context['metrics'] = simplejson.dumps(metrics) return context
def get_checks(self): adwords_adapter = Adapter(self.request.user) return [ check_class(adwords_adapter) for check_class in ( CompatibilityCheckWebsiteTracking, CompatibilityCheckECommerceTracking, CompatibilityCheckOnPagePhoneCallTracking, ) ]
def setup_customer_choices(self, refresh_token): try: try: # Try to get manager account customers = Adapter.get_customers(refresh_token) choices = [(customer.customerId, customer.name) for customer in customers if not customer.canManageClients] except: # In the event of failure, get normal customer = Adapter.get_customer(refresh_token) choices = [(customer.customerId, customer.descriptiveName)] except: raise NonManagerAccountSelected # Ignore manager accounts, as reports can't be run against them. # https://developers.google.com/adwords/api/docs/common-errors#ReportDefinitionError.CUSTOMER_SERVING_TYPE_REPORT_MISMATCH # noqa self.fields['client_customer'].choices = choices
def get_payment_amount_required(self, force_recalculate=False): if hasattr(self, '_payment_amount_required') and not force_recalculate: return self._payment_amount_required now = datetime.datetime.now() if now.time() < datetime.time(hour=3): raise TooEarlyError( 'Data is only available for the previous day from 3AM.' ' Please try again later.') adapter = Adapter(self) monthly_spend = adapter.get_monthly_spend() spend_since_last_billed = adapter.get_spend_for_period( self.payment_last_taken_at, now.date()) self._payment_amount_required = (spend_since_last_billed * get_pricing().get_fee(monthly_spend) / 100) print("Step Final") return self._payment_amount_required
def test_get_metric_shape_returns_correct_shape(self): metrics = {1: {2: 4, 8: ''}} metrics_list = [{16: 32, 64: ''}] empty_metrics = {} self.assertEqual( Adapter.get_metrics_shape(metrics), { 2: 0, 8: 0 }, ) self.assertEqual( Adapter.get_metrics_shape(metrics_list), { 16: 0, 64: 0 }, ) self.assertEqual(Adapter.get_metrics_shape(empty_metrics), {})
def test_aggregate_metrics_to_monthly_is_correct_for_uncast_dates_with_averaged_columns( self): data = { '2017-08-02': { 'conversions': 1, 'cpc': 2, 'cost': 4 }, '2017-08-04': { 'conversions': 8, 'cpc': 16, 'cost': 32 }, '2017-09-02': { 'conversions': 64, 'cpc': 128, 'cost': 256 }, '2016-08-08': { 'conversions': 512, 'cpc': 1024, 'cost': 2048 }, } expected = { '2017-08-01': { 'conversions': 9, 'cpc': 9, 'cost': 36 }, '2017-09-01': { 'conversions': 64, 'cpc': 128, 'cost': 256 }, '2016-08-01': { 'conversions': 512, 'cpc': 1024, 'cost': 2048 }, } self.assertEqual( Adapter.aggregate_metrics_to_monthly(data, date_format='%Y-%m-%d', average_columns=('cpc', )), expected, )
def test_aggregate_metrics_to_monthly_is_correct_with_averaged_columns( self): data = { date(2017, 8, 2): { 'conversions': 1, 'cpc': 2, 'cost': 4 }, date(2017, 8, 4): { 'conversions': 8, 'cpc': 16, 'cost': 32 }, date(2017, 9, 2): { 'conversions': 64, 'cpc': 128, 'cost': 256 }, date(2016, 8, 8): { 'conversions': 512, 'cpc': 1024, 'cost': 2048 }, } expected = { date(2017, 8, 1): { 'conversions': 9, 'cpc': 9, 'cost': 36 }, date(2017, 9, 1): { 'conversions': 64, 'cpc': 128, 'cost': 256 }, date(2016, 8, 1): { 'conversions': 512, 'cpc': 1024, 'cost': 2048 }, } self.assertEqual( Adapter.aggregate_metrics_to_monthly(data, average_columns=('cpc', )), expected, )
def test_aggregate_metrics_is_correct_with_average_columns(self): data = [ { 0: 1, 2: 4 }, { 0: 8, 2: 16 }, ] expected = {0: 4.5, 2: 20} self.assertEqual( Adapter._aggregate_metrics(data, average_columns=(0, )), expected, )
def test_aggregate_metrics_is_correct(self): data = [ { 0: 1, 2: 4 }, { 0: 8, 2: 16 }, ] expected = {0: 9, 2: 20} self.assertEqual( Adapter._aggregate_metrics(data), expected, )
def getAdapter(self): return Adapter(self)
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if not self.request.user.has_adwords_account: return context context['has_adwords_account'] = True date_range_form = DateRangeForm() date_from = date_range_form.fields['date_from'].initial() date_to = date_range_form.fields['date_to'].initial() should_aggregate = date_range_form.fields['should_aggregate'].initial if 'date_from' in self.request.GET and 'date_to' in self.request.GET: date_range_form = DateRangeForm(self.request.GET.copy()) if date_range_form.is_valid(): date_from = date_range_form.cleaned_data['date_from'] date_to = date_range_form.cleaned_data['date_to'] should_aggregate = date_range_form.cleaned_data[ 'should_aggregate'] context['date_range_form'] = date_range_form context['chart_range'] = self.request.GET.get('chart_range', 'last30Days') adapter = Adapter(self.request.user) kwargs = {'cast_dates': False} if context['chart_range'] != 'allTime': kwargs['date_range'] = adapter.format_date_range( date_from, date_to) metrics = adapter.get_campaign_metrics(**kwargs) if should_aggregate: metrics = adapter.aggregate_campaign_metrics_to_monthly( metrics, date_format='%Y-%m-%d') for metric in metrics.values(): metric['cpc'] /= 10**6 context['metrics'] = simplejson.dumps(metrics) event_date_range = self.request.GET.get('range', 'today').lower() date_range_lengths = {'today': 1, 'week': 7, 'month': 28} with connection.cursor() as cursor: cursor.execute( "SELECT campaign_modifiers_keywordevent.action, COUNT(*) FROM campaign_modifiers_keywordevent INNER JOIN campaign_modifiers_modifierprocesslog ON campaign_modifiers_keywordevent.modifier_process_log_id=campaign_modifiers_modifierprocesslog.id INNER JOIN reports_campaign ON campaign_modifiers_modifierprocesslog.adwords_campaign_id=reports_campaign.adwords_campaign_id WHERE reports_campaign.owner_id = %s AND campaign_modifiers_keywordevent.created_at BETWEEN NOW() - INTERVAL %s DAY AND NOW() GROUP BY captivise.campaign_modifiers_keywordevent.action;", [self.request.user.id, date_range_lengths[event_date_range]]) events = cursor.fetchall() increased = 0 decreased = 0 unchanged = 0 paused = 0 for event in events: if event[0] == "increased_cpc": increased = event[1] if event[0] == "decreased_cpc": decreased = event[1] if event[0] == "no_action": unchanged = event[1] if event[0] == "paused": paused = event[1] context.update({ 'increased_bid_count': increased, 'decreased_bid_count': decreased, 'unchanged_bid_count': unchanged, 'paused_keywords_count': paused, }) return context
def run_scripts(): from adwords.adapter import Adapter from accounts.models import User from .modifiers.hcpa import HighCostPerAcquisitionModifier from .modifiers.lcpa import LowCostPerAcquisitionModifier from .modifiers.lctr import LowClickThroughRate from .modifiers.lp import LowPosition from .modifiers.pause_empty_ad_groups import PauseEmptyAdGroups from .modifiers.tcpa import TargetCostPerAcquisition from .modifiers.tcpa_margin import TargetCostPerAcquisitionMargin from .modifiers.zc import ZeroClicks from .modifiers.zc_margin import ZeroClicksMargin from .utils import ModifierProcess for user in User.objects.all(): if not user.has_payment_details: continue # Skip unpaid users. api_adapter = Adapter(user) for campaign in user.campaigns.filter(is_managed=True): if campaign.conversion_type == campaign.CONVERSION_TYPE_CPA: modifiers_in_order = ( PauseEmptyAdGroups(), LowPosition(), ZeroClicks(), LowClickThroughRate(), TargetCostPerAcquisition(), LowCostPerAcquisitionModifier(), HighCostPerAcquisitionModifier(), ) elif campaign.conversion_type == campaign.CONVERSION_TYPE_MARGIN: modifiers_in_order = ( PauseEmptyAdGroups(), LowPosition(), ZeroClicksMargin(), LowClickThroughRate(), TargetCostPerAcquisitionMargin(), ) else: logger = logging.getLogger('celery') message = ('Error while running modifiers on campaign id' ' {campaign_id} for user id {user_id} - unknown' ' `conversion_type`').format( campaign_id=campaign.id, user_id=user.id) logger.error(message) continue try: ModifierProcess().run( modifiers_in_order, api_adapter, campaign.adwords_campaign_id, is_dry_run=user.is_adwords_dry_run, target_cpa=campaign.target_cpa, max_cpc_limit=campaign.max_cpc_limit, cycle_period=campaign.cycle_period_days, ) except: # Don't let one user bring down everyone's scripts. logger = logging.getLogger('celery') message = ('Error while running modifiers on campaign id' ' {campaign_id} for user id {user_id}').format( campaign_id=campaign.id, user_id=user.id) logger.exception(message)