Esempio n. 1
0
    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
Esempio n. 2
0
 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)
Esempio n. 3
0
    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
Esempio n. 4
0
 def get_checks(self):
     adwords_adapter = Adapter(self.request.user)
     return [
         check_class(adwords_adapter) for check_class in (
             CompatibilityCheckWebsiteTracking,
             CompatibilityCheckECommerceTracking,
             CompatibilityCheckOnPagePhoneCallTracking,
         )
     ]
Esempio n. 5
0
    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
Esempio n. 6
0
    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
Esempio n. 7
0
    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), {})
Esempio n. 8
0
    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,
        )
Esempio n. 9
0
    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,
        )
Esempio n. 10
0
    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,
        )
Esempio n. 11
0
    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,
        )
Esempio n. 12
0
 def getAdapter(self):
     return Adapter(self)
Esempio n. 13
0
    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
Esempio n. 14
0
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)