{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Create Text Ads From Scratch\n", "\n", "### Generate multiple ads by dynamically inserting words into their proper place in the text ads\n", "\n", "We will use Python's string formatting capabilities to dynamically generate multiple ads for large-scale campaigns. \n", "\n", "Online text ads usually consist of a few slots. For exmaple, the expanded text ads of Google AdWords and Bing Ads consist of the following slots:\n", "\n", "\n", "\n", "\n", "![](textad_diagram.png) \n", "Here is an actual ad:\n", "\n", "![](text_ad_screen_shot.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lengths of the slots should be at most a certain given length. \n", "Typically, you would want to create multiple ads, for multiple products, using the same template, but changing a word or a phrase within the ad.\n", "\n", "Here is an example for one ad slot: \n", "**Template:** 'Learn { } interactively' \n", "**Maximum length:** 35 \n", "**Replacements:** 'graphic design', 'visual arts', 'fundamentals of user experience' \n", "**Fallback:** 'graphic arts' (what to put in the braces if the total lengh is greater than the maximum allowed length) \n", "\n", "Running the function on each of the above replacements should return the following:\n", "\n", "Learn _graphic design_ interactively ('graphic design') \n", "Learn _visual arts_ interactively ('visual arts') \n", "Learn _graphic arts_ interactively ('fundamentals of user experience') \n", "\n", "Errors to check for: \n", "* Make sure the length of the `template` together with the `fallback` string is at most the maximum length. \n", "* Make sure the same is true for each of the given `replacements` strings, otherwise insert the fallback. \n", "\n", "Another example, with code:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception reporting mode: Plain\n" ] } ], "source": [ "%xmode plain \n", "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "template = 'Get the Latest {}'\n", "fallback = 'Mobile'\n", "replacements = ['iPhone', 'Sony XZ', 'Samsung', 'sony xperia xz premium']\n", "max_len = 25" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "ad_list = []\n", "if len(template.format(fallback)) > max_len:\n", " raise ValueError\n", "for r in replacements:\n", " if len(template.format(r)) <= max_len:\n", " ad_list.append(template.format(r))\n", " else:\n", " ad_list.append(template.format(fallback))" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Get the Latest iPhone',\n", " 'Get the Latest Sony XZ',\n", " 'Get the Latest Samsung',\n", " 'Get the Latest Mobile']" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ad_list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The last one was longer than `max_len` and so 'Mobile' was inserted instead of 'sony xperia xz premium'.\n", "\n", "Putting it in a function:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def ad_create(template, replacements, fallback, max_len=20):\n", " if len(template.format(fallback)) > max_len:\n", " raise ValueError('template + fallback should be <= 20 chars')\n", " final_ad = []\n", " for rep in replacements:\n", " if len(template.format(rep)) <= max_len:\n", " final_ad.append(template.format(rep))\n", " else:\n", " final_ad.append(template.format(fallback))\n", " return final_ad" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['My Car is a BMW', 'My Car is a Mercedes', 'My Car is a Beauty']" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ad_create('My Car is a {}', ['BMW', 'Mercedes', 'Lamborghini'], 'Beauty', 20)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "template + fallback should be <= 20 chars", "output_type": "error", "traceback": [ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n", " File \u001b[1;32m\"\"\u001b[0m, line \u001b[1;32m3\u001b[0m, in \u001b[1;35m\u001b[0m\n 'Beauty Beauty Beauty Beauty ', 20)\n", "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m3\u001b[0;36m, in \u001b[0;35mad_create\u001b[0;36m\u001b[0m\n\u001b[0;31m raise ValueError('template + fallback should be <= 20 chars')\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m\u001b[0;31m:\u001b[0m template + fallback should be <= 20 chars\n" ] } ], "source": [ "# this should raise an exception\n", "ad_create('My Car is a {}', ['BMW', 'Mercedes', 'Lamborghini'], \n", " 'Beauty Beauty Beauty Beauty ', 20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It raises a `ValueError` as it should. \n", "Now we want to create a set of ads for a travel website. \n", "As a reminder the default template we will be using is the expanded text ads used by Google AdWords and BingAds, which is: \n", "\n", "Ad Slot| Maximum Length\n", "-------|-------------------\n", "Headline 1| 30\n", "Headline 2| 30\n", "Description| 80\n", "Path1| 15\n", "Path2| 15\n", "Final URL| 1024\n", "\n", "Templates we are going to use: \n", "\n", "Ad Slot| Maximum Length\n", "-------|-------------------\n", "Headline 1| Trips to {destination}\n", "Headline 2| Prices Starting at ${price}\n", "Description| Enjoy {destination} and Other Great Cities. Browse the Different Options Now.\n", "Path1| {destination}\n", "Path2| {country}\n", "Final URL| http://www.mysite.com/trips/destinations/{destination}\n", "\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "destinations = ['Rio de Janeiro', 'New York', 'Paris', 'Rome', \n", " 'Madrid', 'Istanbul', 'Dubai', 'Los Angeles']\n", "countries = ['Brazil', 'USA', 'France', 'Italy', 'Spain', \n", " 'Turkey', 'UAE', 'USA']\n", "prices = [500, 700, 600, 800, 400, 500, 800, 500]\n", "\n", "templates = {\n", "'Headline 1': 'Trips to {}',\n", "'Headline 2': 'Prices Starting at ${}',\n", "'Description': 'Enjoy {} and Other Great Cities. Browse the Different Options. Start Now',\n", "'Path1': '{}',\n", "'Path2': '{}',\n", "'Final URL': 'http://www.mysite.com/trips/destinations/{}',\n", "}\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Trips to Rio de Janeiro',\n", " 'Trips to New York',\n", " 'Trips to Paris',\n", " 'Trips to Rome',\n", " 'Trips to Madrid',\n", " 'Trips to Istanbul',\n", " 'Trips to Dubai',\n", " 'Trips to Los Angeles']" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h1 = ad_create(template=templates['Headline 1'], \n", " replacements=destinations, \n", " fallback='Great Cities',\n", " max_len=30)\n", "h1" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Prices Starting at $500',\n", " 'Prices Starting at $700',\n", " 'Prices Starting at $600',\n", " 'Prices Starting at $800',\n", " 'Prices Starting at $400',\n", " 'Prices Starting at $500',\n", " 'Prices Starting at $800',\n", " 'Prices Starting at $500']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h2 = ad_create(templates['Headline 2'], prices, '350', 30)\n", "h2" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Enjoy This and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy New York and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy Paris and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy Rome and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy Madrid and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy Istanbul and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy Dubai and Other Great Cities. Browse the Different Options. Start Now',\n", " 'Enjoy This and Other Great Cities. Browse the Different Options. Start Now']" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "desc = ad_create(templates['Description'], destinations, 'This', 80)\n", "desc" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Rio de Janeiro',\n", " 'New York',\n", " 'Paris',\n", " 'Rome',\n", " 'Madrid',\n", " 'Istanbul',\n", " 'Dubai',\n", " 'Los Angeles']" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "path1 = ad_create(templates['Path1'], destinations, '', 15)\n", "path1" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Brazil', 'USA', 'France', 'Italy', 'Spain', 'Turkey', 'UAE', 'USA']" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "path2 = ad_create(templates['Path2'], countries, '', 15)\n", "path2" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['http://www.mysite.com/trips/destinations/Rio de Janeiro',\n", " 'http://www.mysite.com/trips/destinations/New York',\n", " 'http://www.mysite.com/trips/destinations/Paris',\n", " 'http://www.mysite.com/trips/destinations/Rome',\n", " 'http://www.mysite.com/trips/destinations/Madrid',\n", " 'http://www.mysite.com/trips/destinations/Istanbul',\n", " 'http://www.mysite.com/trips/destinations/Dubai',\n", " 'http://www.mysite.com/trips/destinations/Los Angeles']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "final_url = ad_create(templates['Final URL'], destinations, '', 1024)\n", "final_url" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We simply put them together in a DataFrame, together with the Campaign and Ad Group names based on the destinations (products) that we have. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
CampaignAd GroupHeadline 1Headline 2DescriptionPath 1Path 2
0SEM_DestinationsRio de JaneiroTrips to Rio de JaneiroPrices Starting at $500Enjoy This and Other Great Cities. Browse the ...Rio de JaneiroBrazil
1SEM_DestinationsNew YorkTrips to New YorkPrices Starting at $700Enjoy New York and Other Great Cities. Browse ...New YorkUSA
2SEM_DestinationsParisTrips to ParisPrices Starting at $600Enjoy Paris and Other Great Cities. Browse the...ParisFrance
3SEM_DestinationsRomeTrips to RomePrices Starting at $800Enjoy Rome and Other Great Cities. Browse the ...RomeItaly
4SEM_DestinationsMadridTrips to MadridPrices Starting at $400Enjoy Madrid and Other Great Cities. Browse th...MadridSpain
5SEM_DestinationsIstanbulTrips to IstanbulPrices Starting at $500Enjoy Istanbul and Other Great Cities. Browse ...IstanbulTurkey
6SEM_DestinationsDubaiTrips to DubaiPrices Starting at $800Enjoy Dubai and Other Great Cities. Browse the...DubaiUAE
7SEM_DestinationsLos AngelesTrips to Los AngelesPrices Starting at $500Enjoy This and Other Great Cities. Browse the ...Los AngelesUSA
\n", "
" ], "text/plain": [ " Campaign Ad Group Headline 1 \\\n", "0 SEM_Destinations Rio de Janeiro Trips to Rio de Janeiro \n", "1 SEM_Destinations New York Trips to New York \n", "2 SEM_Destinations Paris Trips to Paris \n", "3 SEM_Destinations Rome Trips to Rome \n", "4 SEM_Destinations Madrid Trips to Madrid \n", "5 SEM_Destinations Istanbul Trips to Istanbul \n", "6 SEM_Destinations Dubai Trips to Dubai \n", "7 SEM_Destinations Los Angeles Trips to Los Angeles \n", "\n", " Headline 2 Description \\\n", "0 Prices Starting at $500 Enjoy This and Other Great Cities. Browse the ... \n", "1 Prices Starting at $700 Enjoy New York and Other Great Cities. Browse ... \n", "2 Prices Starting at $600 Enjoy Paris and Other Great Cities. Browse the... \n", "3 Prices Starting at $800 Enjoy Rome and Other Great Cities. Browse the ... \n", "4 Prices Starting at $400 Enjoy Madrid and Other Great Cities. Browse th... \n", "5 Prices Starting at $500 Enjoy Istanbul and Other Great Cities. Browse ... \n", "6 Prices Starting at $800 Enjoy Dubai and Other Great Cities. Browse the... \n", "7 Prices Starting at $500 Enjoy This and Other Great Cities. Browse the ... \n", "\n", " Path 1 Path 2 \n", "0 Rio de Janeiro Brazil \n", "1 New York USA \n", "2 Paris France \n", "3 Rome Italy \n", "4 Madrid Spain \n", "5 Istanbul Turkey \n", "6 Dubai UAE \n", "7 Los Angeles USA " ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ads_df = pd.DataFrame({\n", " 'Campaign': 'SEM_Destinations',\n", " 'Ad Group': destinations,\n", " 'Headline 1': h1,\n", " 'Headline 2': h2,\n", " 'Description': desc,\n", " 'Path 1': path1,\n", " 'Path 2': path2,\n", " 'Final URL': final_url\n", "})\n", "ads_df = ads_df[['Campaign', 'Ad Group', 'Headline 1', 'Headline 2', \n", " 'Description', 'Path 1', 'Path 2']]\n", "ads_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This now ready for uploading, and launching. \n", "Of course the other big part of the account is the keywords, which also need to be generated. \n", "\n", "I'll cover these in another notebook. \n", "\n", "The function `ad_create` is now part of the [advertools](https://www.github.com/eliasdabbas/advertools) package, so you can test it! " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" } }, "nbformat": 4, "nbformat_minor": 2 }