class CarouselAdForm(ComponentForm): ad_account = AdAccountSelect() pageid = PageSelect() bid = BidComponent('bid', Campaign.Objective.link_clicks) name = forms.CharField( initial='Carousel Ads', widget=forms.TextInput(attrs={'placeholder': 'Campaign name'})) targeting_spec = TargetingSpec() site_link = forms.CharField(widget=forms.TextInput( attrs={'placeholder': 'Link to your site'})) caption = forms.CharField(initial='Caption') message = forms.CharField(initial='Message') call_to_action_type = CTASelect() title = forms.CharField(initial='Title 1') title2 = forms.CharField(initial='Title 2') title3 = forms.CharField(initial='Title 3') body = forms.CharField(initial='Body 1') body2 = forms.CharField(initial='Body 2') body3 = forms.CharField(initial='Body 3') url = forms.URLField(widget=forms.TextInput( attrs={'placeholder': 'Item 1 link'})) url2 = forms.URLField(widget=forms.TextInput( attrs={'placeholder': 'Item 2 link'})) url3 = forms.URLField(widget=forms.TextInput( attrs={'placeholder': 'Item 3 link'})) image = ImageInput() image2 = ImageInput(id='id_image2') image3 = ImageInput(id='id_image3')
class AccountForm(ComponentForm): ad_account = AdAccountSelect() # STATUSES = ( # ('False', 'Do not include ARCHIVED ad sets'), # ('True', 'Include ARCHIVED ad sets'), # ) # include_archived = forms.ChoiceField( # widget=forms.RadioSelect, # choices=PLATFORMS, # initial='Android', # help_text='Platform needs to match the platform in targeting above' # ) include_archived = forms.BooleanField( label="Include archived ad sets?", initial=False, required=False, ) limit = forms.DecimalField( label="How many ad sets to check. The more you pick, the longer it " + "will take.", min_value=1, max_value=50, required=True, initial=10)
class AdCreationForm(ComponentForm): ad_account = AdAccountSelect() page = PageSelect() name = forms.CharField(initial='Creative Testing') GENDERS_CHOICES = ( ('0', 'All'), ('1', 'Male'), ('2', 'Female'), ) bid = BidComponent('bid', Campaign.Objective.link_clicks) targeting = TargetingSpec() TOMORROW = datetime.date.today() + datetime.timedelta(days=1) start_time = DatetimePicker( id='id_starttime', initial=TOMORROW, required=False, ) end_time = DatetimePicker(id='id_endtime', required=False) url = forms.URLField( widget=forms.TextInput(attrs={'placeholder': 'Link'})) title = forms.CharField(initial='Title 1') title2 = forms.CharField(initial='Title 2') body = forms.CharField(initial='Body 1') body2 = forms.CharField(initial='Body 2') image = ImageInput() image2 = ImageInput(id="id_image2") image3 = ImageInput(id="id_image3")
class AppInstallAdForm(ComponentForm): """ We need these parameters for the sample script: account_id: AdAccountSelect base_name: TextInput message: TextInput image_path: ImageInput daily_budget: DecimalField page_id: PageSelect app_id: AppSelect app_name: AppSelect app_store_link: AppSelect deferred_app_link: TextInput bid_info: BidComponent targeting: TargetingSpec """ ad_account = AdAccountSelect() name = forms.CharField( label='Basename for your ad', widget=forms.TextInput(attrs={'placeholder': 'App Install'}), help_text='''We will generate campaign name, adset name and ad name with basename.''') page = PageSelect(help_text='Your ad will be published from this page.') app = AppSelect() image = ImageInput(allow_empty_file=False, required=True) message = forms.CharField(label='Ad Message', initial='Try out this awesome app!') app_link = forms.CharField( label='Deferred app link to your app', min_length=4, required=False, widget=forms.TextInput(attrs={'placeholder': 'example://detail/1234'})) targeting = TargetingSpec(initial=targeting_info_initial) PLATFORMS = ( ('Android', 'Android'), ('iOS', 'iOS'), ) platform = forms.ChoiceField( widget=forms.RadioSelect, choices=PLATFORMS, initial='Android', help_text='Platform needs to match the platform in targeting above') bid_info = BidComponent('bid_info', Campaign.Objective.mobile_app_installs) daily_budget = forms.DecimalField(min_value=1, initial=1000) def clean(self): self.cleaned_data = super(AppInstallAdForm, self).clean() self.cleaned_data = \ super(AppInstallAdForm, self).validate_mobile_platform_targeting() return self.cleaned_data
class CustomAudienceForm(ComponentForm): ad_account = AdAccountSelect() name = forms.CharField(max_length=50) description = forms.CharField(max_length=100, required=False) optout_link = forms.URLField() data_file = FileInput( max_length=5242880, allow_empty_file=False, help_text='''Data format: one hash per line.''', )
class MacaFrequencyForm(ComponentForm): ad_account = AdAccountSelect() app = AppSelect() name = forms.CharField(initial='Test Mobile App Custom Audience') retention_days = forms.IntegerField(help_text=RETENTION_HELP, initial=180, validators=[validate_retention_days]) event = forms.ChoiceField(choices=EVENT_CHOICES) period = forms.ChoiceField(choices=PERIOD_CHOICES, help_text=PERIOD_HELP) greater_than = forms.IntegerField(help_text=GREATER_THAN_HELP, required=False) less_than = forms.IntegerField(help_text=LESS_THAN_HELP, required=False)
class TieredLookalikeForm(ComponentForm): TOMORROW = datetime.date.today() + datetime.timedelta(days=1) ad_account = AdAccountSelect() CA_NAME_HELP_TEXT = 'This name will be used to create ' + \ 'the lookalike audiences.' CA_HELP_TEXT = 'Choose a existing custom audience id as the seed ' + \ 'for the lookalike audiences.' """ Information for the uploaded custom audience """ lookalike_audience_name = forms.CharField( max_length=50, help_text=CA_NAME_HELP_TEXT, ) """ Choose to create based on existing custom audience """ seed_id = CustomAudienceSelect() NAME_HELP_TEXT = 'Name for the campaign and ads.' """ Created lookalike campaign information """ name = forms.CharField( initial='Tiered lookalikes', max_length=50, help_text=NAME_HELP_TEXT, ) country = CountrySelect() bid_info = BidComponent('bid_info', Campaign.Objective.link_clicks) help_text = ( '5 bid amounts will be generated between min and max bid. This will ' + 'replace the bid amount you chose in the bid component above.') bid_min = forms.IntegerField(initial=100, help_text=help_text) bid_max = forms.IntegerField(initial=500, help_text=help_text) budget_type = BudgetTypeSelect() budget = forms.IntegerField(initial=1000) start_time = DatetimePicker(id='id_starttime', initial=TOMORROW) end_time = DatetimePicker(id='id_endtime', required=False) title = forms.CharField(initial='Ad title') body = forms.CharField(initial='Ad body.') url = forms.URLField() image = ImageInput()
class ComponentGalleryForm(ComponentForm): select_account = AdAccountSelect() select_account.JS_FILES = ['actselect.js'] select_custom_audience = CustomAudienceSelect() select_custom_audience.JS_FILES = ['caselect.js'] select_app = AppSelect() select_app.JS_FILES = ['app_select.js', 'app_info.jsx'] targeting_setting = TargetingSpec() targeting_setting.JS_FILES = [ 'targeting_spec.js', 'targeting_composer.jsx' ] bid_setting = BidComponent('bid_setting') bid_setting.JS_FILES = ['bid_component.js', 'bid_composer.jsx'] select_page = PageSelect() select_page.JS_FILES = ['page_select.js'] select_lead_gen_form = LeadFormCreate() select_lead_gen_form.JS_FILES = ['lead_form.js', 'lead_form_select.jsx'] select_business_manager = BusinessManagerSelect() select_business_manager.JS_FILES = ['business_select.js'] select_product_catalog = ProductCatalogSelect() select_product_catalog.JS_FILES = ['product_catalog_select.js'] select_product = ProductSelect() select_product.JS_FILES = ['product_select.js'] def __init__(self): super(ComponentGalleryForm, self).__init__() for key, field in self.fields.items(): field.desc = markdown.markdown(textwrap.dedent(field.__doc__)) field.name = field.__class__.__name__ js_modules = [] if hasattr(field, 'JS_FILES'): for js_file in field.JS_FILES: js_module_content = get_file_content( './js_src/{0}'.format(js_file)) js_modules.append({ 'name': js_file, 'content': js_module_content }) field.js_modules = js_modules
class AdsReportingForm(ComponentForm): ad_account = AdAccountSelect() LAST_90_DAYS = datetime.date.today() - datetime.timedelta(days=90) TODAY = datetime.date.today() report_date = DatetimePicker( id='id_reportdate', initial=TODAY.strftime('%Y-%m-%d'), datetime_format='YYYY-MM-DD', min_date=LAST_90_DAYS.strftime('%Y-%m-%d'), max_date=TODAY.strftime('%Y-%m-%d'), help_text='Date between last 90 days and today', )
class MultipleLalForm(ComponentForm): ad_account = AdAccountSelect() base_name = forms.CharField(max_length=50) seed_id = CustomAudienceSelect() country = CountrySelect() country_2 = CountrySelect(id='country_2', required=False) country_3 = CountrySelect(id='country_3', required=False) ratio = forms.IntegerField( min_value=1, max_value=10, help_text='Lookalike percentage value, from 1 to 10') ratio_2 = forms.IntegerField(min_value=1, max_value=10, required=False) ratio_3 = forms.IntegerField(min_value=1, max_value=10, required=False)
class ProductAudienceEstimationForm(ComponentForm): ad_account = AdAccountSelect() business_manager = BusinessManagerSelect() product_catalog = ProductCatalogSelect() product_set = ProductSetSelect() targeting_spec = SpecSelect(specs=TARGETING_SPECS) def clean(self): self.cleaned_data = super(ProductAudienceEstimationForm, self).clean() self.cleaned_data = \ super(ProductAudienceEstimationForm, self).validate_mobile_platform_targeting() return self.cleaned_data
class LeadAdForm(ComponentForm): ad_account = AdAccountSelect() page = PageSelect() lead_form = LeadFormCreate() name = forms.CharField(initial='My First Lead Ad') targeting = TargetingSpec(initial=targeting_info_initial) bid_info = BidComponent('bid_info', Campaign.Objective.lead_generation) daily_budget = forms.DecimalField( min_value=1, initial='500', ) image = ImageInput( allow_empty_file=False, required=True, ) message = forms.CharField(initial='My First Lead Ad') link = forms.CharField() caption = forms.CharField() description = forms.CharField()
class AppEngagementForm(ComponentForm): IMAGE_MIN_WIDTH = 1200 IMAGE_MIN_HEIGHT = 627 ad_account = AdAccountSelect() name = forms.CharField( label='Basename for your ads', max_length=50, required=True, widget=forms.TextInput(attrs={'placeholder': 'My App Engagement'}), help_text='''We will generate campaign name, adset name and ad name with basename.''' ) page = PageSelect() image = ImageInput( allow_empty_file=False, required=True, help_text='PNG or JPG file with width=1200px, height=627px' ) message = forms.CharField( label='Ad Message', max_length=90, required=True, initial='Try out this feature in our app!' ) app = AppSelect() deep_link = forms.CharField( label='Deep link to your app action', min_length=4, required=True, widget=forms.TextInput(attrs={'placeholder': 'example://detail/1234'}) ) pixel = forms.CharField( label='Facebook offsite pixel id of your app', min_length=1, required=True, initial='null', help_text='Fill `null` to skip.' ) targeting = TargetingSpec(initial=targeting_info_initial) PLATFORMS = ( ('Android', 'Android'), ('iOS', 'iOS'), ) platform = forms.ChoiceField( widget=forms.RadioSelect, choices=PLATFORMS, help_text='Platform needs to match the platform in targeting above' ) bid_info = BidComponent('bid_info', 'MOBILE_APP_ENGAGEMENT') daily_budget = forms.DecimalField( min_value=1, required=True, initial='500', help_text='to bid $5.00, set 500' ) def clean_image(self): image = self.cleaned_data.get('image') if not image: raise forms.ValidationError('Not an image!') else: w, h = get_image_dimensions(image) if w < AppEngagementForm.IMAGE_MIN_WIDTH: raise forms.ValidationError( "The image is %i pixel wide. It's supposed to be >= %i." % (w, AppEngagementForm.IMAGE_MIN_WIDTH) ) if h < AppEngagementForm.IMAGE_MIN_HEIGHT: raise forms.ValidationError( "The image is %i pixel high. It's supposed to be >= %i." % (h, AppEngagementForm.IMAGE_MIN_HEIGHT) ) return image def clean(self): self.cleaned_data = super(AppEngagementForm, self).clean() self.cleaned_data = \ super(AppEngagementForm, self).validate_mobile_platform_targeting() return self.cleaned_data
class AudienceNetworkOptInForm(ComponentForm): ad_account = AdAccountSelect() adset = AdSetSelect()
class AutobotConfigEditorForm(ComponentForm): ad_account = AdAccountSelect( help_text='* Only one ad account is supported through the config UI.') app = AppSelect(help_text='Select your application in the pop up') name = forms.CharField(label='Name', max_length=128, required=True, initial='My Autobot config') page = PageSelect(help_text='Select your Page in the pop up') PLATFORMS = ( ('Android', 'Android'), ('iOS', 'iOS'), ('Canvas', 'Canvas'), ) access_token = forms.CharField(label='System Token', max_length=201, required=True, initial='- system access token -', help_text="Paste system access token.") adset_life = forms.IntegerField( label='Ad Set Life', required=True, max_value=180, min_value=1, initial=14, ) lifetime_budget = forms.IntegerField( label='Lifetime Budget', required=True, max_value=1000000, min_value=0, initial=7500, ) age_min = forms.IntegerField( label='Age Minimum', required=True, max_value=65, min_value=13, initial=18, ) interests = InterestSelect( required=False, help_text='Type interest to lookup or find suggestions.') min_purchase_percentage = forms.DecimalField( label='Minimum purchase (%)', required=True, max_value=1.00, min_value=0.00, decimal_places=2, initial=0.25, help_text="""Autobot will automatically include all countries that have purchase values exceeding this percentage.""") forced_countries = CountrySelect( id='id_forced_countres_select', multiple=True, required=False, ) ignored_countries = CountrySelect( id='id_ignore_countries_select', multiple=True, required=False, ) margin_requirement = forms.DecimalField( label='Margin Requirement', required=True, max_value=2.00, min_value=0.00, decimal_places=2, initial=1.15, help_text="""Scales the bid Autobot creates; intended to account for any overhead incurred between purchase value and actual profit.""") scale_targeting_type = forms.CharField( label='Scale Targeting', initial='''{"INTEREST": 0.7, "LOOKALIKE": 1.0, \ "WIDE_LOOKALIKE": 0.9, "BROAD": 0}''', help_text=""" Multiplies the bid Autobot creates based on the type of ad being run. INTEREST of 1 means full bid, while BROAD 0.25 means 1/4 for broad targeting. The options are INTEREST, LOOKALIKE, WIDE_LOOKALIKE, and BROAD""") platforms = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple( attrs={'id': 'id_platform_select'}), choices=PLATFORMS, initial=(PLATFORMS[0])) # https://developers.facebook.com/docs/marketing-api/targeting-specs/v2.7 ANDROID_VERSIONS = ( (2.0, '2.0'), (2.1, '2.1'), (2.2, '2.2'), (2.3, '2.3'), (3.0, '3.0'), (3.1, '3.1'), (3.2, '3.2'), (4.0, '4.0'), (4.1, '4.1'), (4.2, '4.2'), (4.3, '4.3'), (4.4, '4.4'), (5.0, '5.0'), (5.1, '5.1'), ) IOS_VERSIONS = ( (2.0, '2.0'), (3.0, '3.0'), (4.0, '4.0'), (4.3, '4.3'), (5.0, '5.0'), (6.0, '6.0'), (7.0, '7.0'), (8.0, '8.0'), (9.0, '9.0'), ) android_version = forms.ChoiceField(label='Android Minimum Version', choices=ANDROID_VERSIONS, initial=4.1, required=False) ios_version = forms.ChoiceField(label='iOS Minimum Version', choices=IOS_VERSIONS, initial=8.0, required=False) asset_feed = AssetFeed(initial=asset_feed_initial) MISC_JSON = ''' { "create_ads": false, "user_adclusters": [], "pltv_days": [0, 28, 90, 182, 365, 545], "pltv_days_strings": ["1d", "28d", "90d", "6mo", "1yr", "18 mo"], "lal_ratio_by_country": { "default": 0.05 }, "lal_source_audience_by_country": { "default": 25 } } ''' misc = forms.CharField( label='Miscellaneous Settings', widget=forms.Textarea, initial=MISC_JSON, ) settings_file = forms.CharField( label='Output Logging File', max_length=128, required=True, initial="autobot_output.json", help_text="Where Autobot will trace output at runtime.") save_filename = forms.CharField(label='Save Config as', max_length=128, required=True, initial="autobot_config.json") def __init__(self, *args, **kwargs): super(AutobotConfigEditorForm, self).__init__(*args, **kwargs) js = """ const name = document.getElementById('id_name'); const app = document.getElementById('id_app_select'); if (name && app) { try { const info = JSON.parse(app.value); if (info.name != name.value) name.value = info.name; } catch(err) {} } """ self.fields['app'].widget.attrs.update({'onblur': js}) def clean(self): self.cleaned_data = super(AutobotConfigEditorForm, self).clean() if 'access_token' in self.cleaned_data: access_token = self.cleaned_data['access_token'] url = construct_url('https://graph.facebook.com/v2.7/me', {'access_token': access_token}) try: urllib2.urlopen(url).read() except urllib2.HTTPError: raise ValidationError('Invalid access token.') return self.cleaned_data
class CarouselAppAdForm(ComponentForm): ad_account = AdAccountSelect() name = forms.CharField( label='Basename for your ads', max_length=50, required=True, widget=forms.TextInput( attrs={'placeholder': 'Carousel App Install Ad'}), help_text='''We will generate campaign name, adset name and ad name with basename.''') message = forms.CharField(label='Ad Message', max_length=90, required=True, initial='Try out this new app!') daily_budget = forms.DecimalField(min_value=1, required=True, initial=1000) bid_info = BidComponent('bid_info', Campaign.Objective.mobile_app_installs) targeting = TargetingSpec( initial=targeting_info_initial, help_text='You need to choose mobile platform and a placement type' + ' that has mobile, and the platform should match with below') PLATFORMS = ( ('Android', 'Android'), ('iOS', 'iOS'), ) platform = forms.ChoiceField( widget=forms.RadioSelect, choices=PLATFORMS, initial='Android', help_text='Platform needs to match the platform in targeting above') appinfo_fbpage_id = PageSelect( help_text='The page from which the ad is posted') app = AppSelect(help_text='Select your application in the pop up') # The carousel contains 3 images image_1 = ImageInput( label='Image 1', allow_empty_file=False, required=True, help_text='PNG or JPG file with width=1200px, height=627px') link_title_1 = forms.CharField( help_text='Title message for image 1', widget=forms.TextInput(attrs={'placeholder': 'My App Name'})) deep_link_1 = forms.CharField( help_text='Deep link for image 1', required=False, widget=forms.TextInput(attrs={'placeholder': 'example://product/123'})) image_2 = ImageInput( id='id_image_2', label='Image 2', allow_empty_file=False, required=True, help_text='PNG or JPG file with width=1200px, height=627px') link_title_2 = forms.CharField( help_text='Title message for image 2', widget=forms.TextInput(attrs={'placeholder': 'My App Name'})) deep_link_2 = forms.CharField( help_text='Deep link for image 2', required=False, widget=forms.TextInput(attrs={'placeholder': 'example://product/123'})) image_3 = ImageInput( id='id_image_3', label='Image 3', allow_empty_file=False, required=True, help_text='PNG or JPG file with width=1200px, height=627px') link_title_3 = forms.CharField( help_text='Title message for image 3', widget=forms.TextInput(attrs={'placeholder': 'My App Name'})) deep_link_3 = forms.CharField( help_text='Deep link for image 3', required=False, widget=forms.TextInput(attrs={'placeholder': 'example://product/123'})) def clean(self): self.cleaned_data = super(CarouselAppAdForm, self).clean() self.cleaned_data = \ super(CarouselAppAdForm, self).validate_mobile_platform_targeting() return self.cleaned_data