Script 249: Title Strategy Assignment

Purpose

The Python script assigns a specific campaign strategy and updates related fields when the “CPA Date” matches the current date.

To Elaborate

The script is designed to automate the assignment of a campaign strategy based on a specific condition related to the “CPA Date.” When the “CPA Date” in the input data matches the current date, the script updates the campaign strategy to “TITLE | AUTOMATION | CPA,” sets the publisher strategy to “ManualCpc,” and clears the “Bidding Movement” field. This process ensures that campaigns are automatically adjusted to a predefined strategy when they reach a certain date, streamlining the management of campaign strategies and ensuring consistency in how campaigns are handled on specific dates.

Walking Through the Code

  1. Initialization and Setup:
    • The script begins by defining constants for column names used in the input and output dataframes.
    • It initializes placeholder values for the output dataframe columns related to strategy, publisher bid strategy, and bidding movement.
  2. Process Function:
    • The process function is defined to handle the main logic of the script.
    • Temporary columns are created in the input dataframe to store potential updates.
    • The script checks if the “CPA Date” in the input data matches the current date. If so, it assigns the specified strategy, publisher bid strategy, and clears the bidding movement.
  3. Change Detection and Output Construction:
    • The script identifies rows where changes have occurred by comparing the temporary columns with the original columns.
    • If changes are detected, it constructs an output dataframe with the updated values, renaming the temporary columns to match the output schema.
  4. Testing and Execution:
    • A test_process function is included to validate the logic using sample data, ensuring the script behaves as expected.
    • The script concludes by processing the input dataframe and printing the final output.

Vitals

  • Script ID : 249
  • Client ID / Customer ID: 1306913736 / 50395
  • Action Type: Bulk Upload (Preview)
  • Item Changed: Campaign
  • Output Columns: Account, Campaign, Strategy, Publisher Bid Strategy, Bidding Movement
  • Linked Datasource: M1 Report
  • Reference Datasource: None
  • Owner: Michael Huang (mhuang@marinsoftware.com)
  • Created by Michael Huang on 2023-07-23 17:17
  • Last Updated by Jeremy Brown on 2023-12-06 04:01
> See it in Action

Python Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#
# Auto Strategy Assignment
#  When "CPA Date" is today:
#   - Assign campaign strategy to "TITLE | CPA $" 
#  - set Publisher Strategy to manualCpc and "Bidding Movement" to blank
#
# Author: Michael S. Huang
# Created: 2023-07-24
# 


RPT_COL_CAMPAIGN = 'Campaign'
RPT_COL_ACCOUNT = 'Account'
RPT_COL_PUBLISHER_BIDSTRATEGY = 'Publisher Bid Strategy'
RPT_COL_BIDDING_MOVEMENT = 'Bidding Movement'
RPT_COL_CPA_DATE = 'CPA Date'
RPT_COL_STRATEGY = 'Strategy'
BULK_COL_ACCOUNT = 'Account'
BULK_COL_CAMPAIGN = 'Campaign'
BULK_COL_STRATEGY = 'Strategy'
BULK_COL_PUBLISHER_BIDSTRATEGY = 'Publisher Bid Strategy'
BULK_COL_BIDDING_MOVEMENT = 'Bidding Movement'

outputDf[BULK_COL_STRATEGY] = "<<YOUR VALUE>>"
outputDf[BULK_COL_PUBLISHER_BIDSTRATEGY] = "<<YOUR VALUE>>"
outputDf[BULK_COL_BIDDING_MOVEMENT] = "<<YOUR VALUE>>"

today = datetime.datetime.now(CLIENT_TIMEZONE).date()
print("today: ", today)

VAL_PUB_STRATEGY_MANUALCPC = 'ManualCpc'
VAL_MARIN_STRATEGY_TITLE_CPA = 'TITLE | AUTOMATION | CPA'
VAL_BIDDING_MOVEMENT_BLANK = ''

def process(inputDf):
    # setup tmp columns
    TMP_COL_PUBLISHER_BIDSTRATEGY = RPT_COL_PUBLISHER_BIDSTRATEGY + '_'
    TMP_COL_STRATEGY = RPT_COL_STRATEGY + '_'
    TMP_COL_BIDDING_MOVEMENT = RPT_COL_BIDDING_MOVEMENT + '_'

    inputDf[TMP_COL_PUBLISHER_BIDSTRATEGY] = np.nan
    inputDf[TMP_COL_STRATEGY] = np.nan
    inputDf[TMP_COL_BIDDING_MOVEMENT] = np.nan

    print("inputDf", inputDf.to_string())

    # apply logic
    inputDf.loc[ inputDf[RPT_COL_CPA_DATE] == today, \
            [TMP_COL_PUBLISHER_BIDSTRATEGY, TMP_COL_STRATEGY, TMP_COL_BIDDING_MOVEMENT] \
          ] = [VAL_PUB_STRATEGY_MANUALCPC, VAL_MARIN_STRATEGY_TITLE_CPA, VAL_BIDDING_MOVEMENT_BLANK]

        # Check for changes
    changed = (inputDf[TMP_COL_PUBLISHER_BIDSTRATEGY].notnull() & (inputDf[TMP_COL_PUBLISHER_BIDSTRATEGY] != inputDf[RPT_COL_PUBLISHER_BIDSTRATEGY])) | \
              (inputDf[TMP_COL_STRATEGY].notnull() & (inputDf[TMP_COL_STRATEGY] != inputDf[RPT_COL_STRATEGY])) | \
              (inputDf[TMP_COL_BIDDING_MOVEMENT].notnull() & (inputDf[TMP_COL_BIDDING_MOVEMENT] != inputDf[RPT_COL_BIDDING_MOVEMENT]))

    if changed.sum() > 0:
        # print changed rows
        print("changed", inputDf[changed].to_string())
        
        # construct outputDf
        outputDf = inputDf[changed][[RPT_COL_ACCOUNT, RPT_COL_CAMPAIGN, TMP_COL_PUBLISHER_BIDSTRATEGY, TMP_COL_STRATEGY, TMP_COL_BIDDING_MOVEMENT]].copy()
        outputDf.rename(columns={ \
                TMP_COL_PUBLISHER_BIDSTRATEGY: BULK_COL_PUBLISHER_BIDSTRATEGY, \
                TMP_COL_STRATEGY: BULK_COL_STRATEGY,
                TMP_COL_BIDDING_MOVEMENT: BULK_COL_BIDDING_MOVEMENT
                }, inplace=True)
        
    else:
        print("No changes detected, returning an empty dataframe")
        outputDf = pd.DataFrame(columns=[BULK_COL_ACCOUNT, BULK_COL_CAMPAIGN, BULK_COL_PUBLISHER_BIDSTRATEGY, BULK_COL_STRATEGY, BULK_COL_BIDDING_MOVEMENT])

    return outputDf

def test_process():

    print("#### UNIT TEST START ####")

    try:
        # Input data with additional columns
        input_data = [
            [
                'Campaign 1', 
                'Account 1', 
                'Max ROAS', 
                'Increase',
                (datetime.datetime.today() - datetime.timedelta(days=1)).date(),
                'Max Conv'
            ],
            [
                'Campaign 2', 
                'Account 1', 
                'Max ROAS', 
                'Increase',
                (datetime.datetime.today() + datetime.timedelta(days=1)).date(),
                'Max Conv'
            ],
            [
                'Campaign 3', 
                'Account 1', 
                'Max ROAS', 
                'Increase',
                datetime.datetime.today().date(),
                'Max Conv'
            ],            
        ]
        
        # Build input dataframe
        inputDf = pd.DataFrame(input_data, columns=[
            RPT_COL_CAMPAIGN,
            RPT_COL_ACCOUNT,
            RPT_COL_PUBLISHER_BIDSTRATEGY,
            RPT_COL_BIDDING_MOVEMENT, 
            RPT_COL_CPA_DATE,
            RPT_COL_STRATEGY
        ])

        # Expected output DataFrame
        expected_output_data = {
            BULK_COL_ACCOUNT: ["Account 1"],
            BULK_COL_CAMPAIGN: ["Campaign 3"],
            BULK_COL_PUBLISHER_BIDSTRATEGY: [VAL_PUB_STRATEGY_MANUALCPC],
            BULK_COL_STRATEGY: [VAL_MARIN_STRATEGY_TITLE_CPA],
            BULK_COL_BIDDING_MOVEMENT: [VAL_BIDDING_MOVEMENT_BLANK],
        }
        expected_outputDf = pd.DataFrame(expected_output_data)

        outputDf = process(inputDf)
        
        # Assertions
        assert len(outputDf) == 1
        # if outputDf.equals(expected_outputDf):
        assert  np.array_equal(expected_outputDf.values, outputDf.values)

        print("#### PASSED ####")
        print("#### UNIT TEST END ####")

    except AssertionError:
        print("#### FAILED ####")
        print("expected", tableize(expected_outputDf), expected_outputDf.dtypes, expected_outputDf.values)
        print("actual", tableize(outputDf), outputDf.dtypes, outputDf.values)
    
# run unit test
test_process()

# Process the inputDf
outputDf = process(inputDf)
print("final output", outputDf.to_string())

Post generated on 2024-11-27 06:58:46 GMT

comments powered by Disqus