Don’t Ask, Don’t Get: How to Secure Budget for Your Team in 2025

Teams across industries are finalizing their 2025 budget proposals.

But how can they get their requests approved?

Lauren McCormack (Vice President, Revenue Pulse) and Brooke Bartos (Director of Marketing Operations & Analytics, InvoiceCloud) have the answers.

Last week, they hosted a practical session on creating compelling budget requests so your marketing team can get the resources it needs for the year ahead.

It features 5 actionable tips for justifying your budget, including a Business Case Template you can view and download here.

Watch the FULL recording above!

7 Tips For Getting Your Budget Approved

This is an important time of year.

We’re in a crucial planning season as teams across industries finalize their budget proposals.

And the question that many marketers have on their mind is:

How can I ensure these budget requests are approved by leadership?

Especially when marketing budgets continue to shrink year-over-year.

Which is why we’ve put together 7 practical tips for creating a budget proposal that leadership can rally behind.

Let’s get into it.

pink line

1. Identify Business Goals

Start by zooming out. Look at the broader business objectives that your company is trying to achieve. Whether you’re looking to enhance brand visibility, capture new customer segments, or support a major product launch, these high-level objectives serve as your guiding lights or “north stars.”

Every line in your budget should trace back to these fundamental goals, demonstrating to leadership that your proposed spending aligns with organizational priorities.
 

2. Understand Your Industry

With business goals in mind, take a closer look at market trends and competitor activities. Understanding your industry lets you emulate proven successful strategies, as well as identify opportunities your competitors have missed.

For example, should you invest in a heavily saturated channel? Or should you explore new channels that no one in your space has leveraged? Maybe there is a case to be made for both. A well-researched competitive analysis can help justify either approach.
 

3. Understand Your Target Audience

You can have the greatest campaign ever with strong branding and impactful copy. But if it’s not being put in front of the right people, it won’t produce the results you’re hoping for.

So if you haven’t already, start by developing data-driven Ideal Customer Profiles (ICPs) – we actually conducted an experiment on using ChatGPT to define your true ICP.

From there, identify leads in your database that match these profiles. Then, craft messaging that speaks directly to their needs, pain points, and decision-making authority.

And remember that audience targeting is an iterative process. Monitor your response rates, test different messaging approaches, and be ready to adapt based on results. Your budget allocation should reflect this commitment to continuous refinement (ie. Instead of allocating all your digital advertising spend upfront, space it out to reflect different phases of testing and optimization month-to-month.)

Note: It’s not enough to just have well-defined ICPs and good messaging; it’s equally important to keep your database up-to-date and free of duplicates. Dirty data will cause all sorts of other problems such as lost revenue and productivity, data privacy violation risks, and unreliable decision-making. Here’s how to create a data hygiene plan that works.
 

4. Determine the Right Marketing Channels

Knowing your audience is only half the battle. You need to meet them where they are. Is it most effective to reach them through social media platforms, SEO strategies, email marketing, TV and print advertising, or all of them?

Evaluate your options and allocate budget across channels that reflect both audience behavior and channel performance data.

But don’t spread yourself too thin either; It’s better to excel on a few key platforms than to maintain a mediocre presence everywhere.
 

5. Learn From Past Performance

Nothing builds credibility like proven success. Review your previous campaigns thoroughly and see what worked and what didn’t. Doing this allows you to learn from previous mistakes, recreate proven strategies, and build on past wins as you expand your scope.

When you’re presenting your budget to leadership, highlight those specific examples where strong ROI was delivered. These examples act as valuable proof of concept, showing that you can be trusted with resources.
 

6. Project Results (Especially Revenue Growth)

Building on your historical analysis from the previous tip, take things one step further by creating detailed projections for future campaigns. Leadership will have more confidence in your vision when you support it with reliable projections backed by good data.

Projected revenue growth is especially important here. Highlighting how your proposed initiatives will directly contribute to increased revenue is a language your CFO (and the entire leadership team) will understand.

It’s also a good idea to develop a system of transparency and accountability through regular check-ins – maybe in the form of a continuously updating model that leadership can monitor throughout the year, for example. This kind of thing will help maintain trust and is generally good practice.
 

7. Focus on the Opportunity

At the end of the day, leadership can overlook cost if the ROI makes sense. This is why it’s important to focus on the opportunity that your budget creates.

When you’re communicating with leadership, focus on the high-level vision. Paint a picture of the potential benefits while showing how your plan aligns with broader organizational goals.

And keep it simple! Overly technical details might lose them. Instead, emphasize value and outcomes.

Because when they trust your vision, they’re far more likely to invest in your plan.

pink line

As we’ve mentioned, marketing budgets are shrinking – which makes compelling budget proposals vital to the success of your team and your company.

In order to get buy-in, you need a convincing narrative backed by solid data. Use these tips to help you create a budget proposal that presents a clear vision for growth that leadership can confidently get behind.

And if you want to dive deeper into this topic, don’t miss our upcoming presentation called “Don’t Ask, Don’t Get: How to Secure Budget for Your Team in 2025”.

Learn more and save your spot here!

How to Revert Data Changes with the Marketo API

This is one of every marketer’s worst nightmares 👻:

Your plate is full and you barely have time to finish your tasks for the day, when your Marketing Manager asks you to upload a list to Marketo ASAP.

You get it done quickly, but your SDR says the leads have the wrong information!

The list is full of bad formatting and incorrect entries.

It’s a disaster. Some leads have already existed in your database for years and now have the wrong job titles, others have come from different sources, etc.

Fortunately, Marketo’s API has a solution – a “time machine” of sorts that allows us to revert data changes.

In this guide, we’ll show you how to roll back your data using the API.

Let’s get into it!

(This guide is for Marketo users and assumes a basic understanding of the Marketo API. If you want to learn more, check out our API webinar and an extensive API course by Tyron Pretorius.)

pink line

Note: Whenever we use the Marketo APIs, remember to obtain a Marketo API access token before anything else. This will be required to communicate with the API.

Step 1. Extract data value change activities.

First, we need to identify the recent data changes that occurred when we uploaded the faulty list. 

Using the Marketo API, we can pull a log of data value change activities. This will give us both the old values and the new (incorrect) values, allowing us to update lead fields with the original old values via the API in later steps. 

Start by acquiring the “paging token” using this code snippet:

 url="https://"+MUNCHKIN+".mktorest.com/rest/v1/activities/pagingtoken.json"
token=get_access_token()
params={'access_token': token,
        'sinceDatetime':sinceDate}
response=requests.get(url=url,params=params)
data=response.json()
nextPageToken=data['nextPageToken']

 
Next, use this code snippet to extract data value change activities:

url="https://"+MUNCHKIN+".mktorest.com/rest/v1/activities.json"
params={'access_token': token,
        'nextPageToken': nextPageToken,
        'activityTypeIds':[13],
        'listId': listID}
response=requests.get(url=url,params=params)
data=response.json()
print(data)
act=data['result']
while data['moreResult']==True:
    nextPageToken=data['nextPageToken']
    token=get_access_token()
    params={'access_token': token,
                'nextPageToken': nextPageToken,
                'activityTypeIds':[13],
                'listId': listID}
    response=requests.get(url=url,params=params)
    data=response.json()
    print(data)
    act=act+(data['result'])

 

Step 2. Isolate the old values from the list import.

Now that we have the activity log, we can pinpoint the old values that were replaced by the faulty list and extract them.

Use this code snippet to do this:

df=pd.json_normalize(act)
df=df[df['primaryAttributeValue']==field]
df=df.sort_values('activityDate')
df=df.reset_index()
df=df.drop(columns=['index'])
df1=pd.json_normalize(df['attributes'])
i=4
while i<len(df1.columns):
    df1=df1.drop(columns=[i])
    i=i+1
df1.columns=['New_Value','Old_Value','Reason','Source','Other']
df1.New_Value=pd.json_normalize(df1.New_Value)['value']
df1.Old_Value=pd.json_normalize(df1.Old_Value)['value']
df1.Reason=pd.json_normalize(df1.Reason)['value']
df1.Source=pd.json_normalize(df1.Source)['value']
df=pd.merge(df,df1,left_index=True, right_index=True)
df=df.drop(columns=['attributes'])
df=df.drop_duplicates(subset='leadId', keep="first")

 

Step 3. Update Marketo fields with the old (original) values.

We can now restore the old values to our leads using the Marketo API. This process requires a specific API call to update each lead’s information back to its original state.

Use this code snippet to get you started:

ids=df[df.columns.to_list()[2]].to_list()
camposval=df['Old_Value'].to_list()
for i in range(len(camposval)):
    if camposval[i] == None:
        camposval[i] = 'NULL'
STEP=300
a=math.ceil(len(ids)/STEP)
i=0
while i < a: 
    tempids=ids[i*STEP:(i+1)*STEP]
    tempcamposval=camposval[i*STEP:(i+1)*STEP]
    params={'action': 'updateOnly',
            'lookupField': 'id',
            'input':[]}
    j=0
    while j<len(tempids):
        lead={'id':tempids[j],
              fieldRest:tempcamposval[j]}
        params['input'].append(lead)
        j=j+1
    token=get_access_token()
    url="https://"+MUNCHKIN+".mktorest.com/rest/v1/leads.json?access_token="+token
    headers={'content-type': 'application/json'}
    i=i+1
    response=requests.post(url=url,data=json.dumps(params), headers=headers)
    print(response.json()['result'])

 
Now, when we look at our Marketo instance, all the lead values should be reverted back to what they were before the faulty list was uploaded – crisis averted!

pink line

With a deep understanding of the Marketo API, we can find efficient solutions like this to problems that would normally require countless hours of manual cleanup.

So, next time you mistakenly upload a bad list, don’t panic!

Use this guide as a framework to quickly and efficiently reverse those changes, ensuring your SDRs have the most accurate lead information possible.

If you need help with this guide or have any other questions about the Marketo API, you can book a chat with us here.

How to Create Programs with the Marketo API

If you’re a Marketo user, you’ll know that it’s great at scaling.

It offers robust templates and tokens to streamline marketing operations.

But with that said, there can still be plenty of manual work involved in the form of cloning programs, updating tokens, and activating smart campaigns.

If you’re running an instance with 10 campaigns per day, for example, that’s going to be a real challenge. And if it has 1000 campaigns per day, it’s pretty much impossible to maintain accuracy and consistency — even if you have an amazing team.

The solution: leverage the Marketo API to automate these repetitive processes.

In this guide, we’ll show you how to harness the Marketo API to save time, ensure consistency, and enable greater scalability across your marketing initiatives.

Let’s get into it!

(This guide is for Marketo users and assumes a basic understanding of the Marketo API. If you want to learn more about the API, check out our webinar as well as an extensive course by Tyron Pretorius.)

pink line

Note: It’s important to remember that we must always start by obtaining a Marketo API access token.

1. Cloning Programs

Imagine you need to create 25 webinar programs that each require unique details. This would be pretty time-consuming to manually complete, so we’re going to use the API to automate the entire process.

Let’s start with a Python script that will automatically clone your program:

def clone_program(programName,programId,folderId):
    url="https://"+MUNCHKIN+".mktorest.com/rest/asset/v1/program/"+programId+"/clone.json"
    token=get_access_token()
    params={'access_token': token,
           "Content-Type": "application/x-www-form-urlencoded"}
    body="name="+programName+"&folder={'id':"+folderId+",'type':'Folder'}"
    url=url+"?"+body
    response=requests.post(url=url,params=params)
    data=response.json()
    programid=data['result'][0]['id']
    return programid 

 

2. Updating Tokens

Now that our programs are cloned, we need to populate them with the correct values. Using the API, we can update text tokens, date tokens, etc. across multiple programs simultaneously — saving time and reducing the risk of outdated information being sent to our audience.

Use this Python script for updating text tokens:

def updateTextToken(programid,tokenName,tokenValue):
    url = "https://"+MUNCHKIN+".mktorest.com/rest/asset/v1/folder/"+str(programid)+"/tokens.json"
    token=get_access_token()
    headers = {
        "Authorization": "Bearer "+token,
        "Content-Type": "application/x-www-form-urlencoded"}
    body="name="+tokenName+"&value="+str(tokenValue)+"&type=text&folderType=Program"
    url=url+"?"+body
    response = requests.post(url, headers=headers)
    data=response.json()

 

3. Activating Smart Campaigns

Finally, we must bring our programs to life by activating our smart campaigns.

Use this last Python script to achieve this:

def activateSC(campaigns):
    for campaign in campaigns:        url="https://"+MUNCHKIN+".mktorest.com/rest/asset/v1/smartCampaign/"+str(campaign)+"/activate.json"
        token=get_access_token()
        params={'access_token': token}
        response=requests.post(url=url,params=params)
        data=response.json()

 

With Great Power Comes Great Responsibility

While the Marketo API opens up a world of automation possibilities, we need to use it wisely.

Here are a few major considerations we want to leave you with:

1. Always have a backup plan.

If you’re going to clone 25 programs, for example, make sure you can delete those 25 programs if necessary. Create a “delete campaign” as a safety net so you can undo any changes.

2. Test, test, test.

In your typical development process, you would usually build things in a lower “beta” environment where everything can be tested. In Marketo, you can’t do this. You need to test things in production to see what your results are going to be.

For example, if you want to update 100 landing pages using the API, start by updating just 1 landing page first. Did the changes to that page go through as planned? If the answer is no, you’ll need to go back and fix things before you bulk-update the next 99 pages. Then retest the change, and so on.

Automation is our friend, but we don’t want to create more technical debt — and we definitely don’t want to create technical debt that we can’t automate.

As long as we keep this in mind and proceed with caution, we’ll be fine!

pink line

By carefully leveraging the Marketo API to automate these repetitive processes, we’re:

✅ Improving consistency
✅ Enabling greater scalability
✅ Freeing up valuable time for more strategic initiatives

And if you need any help using the Marketo API, book a 30-min call with one of our experts here!

How to Perform Deduplication using the Marketo API

Nearly every Marketo instance will eventually have duplicate leads.

They can come from list uploads, form fills, CRM syncs, manual lead creation, and much more.

And since Marketo subscription costs scale with database size, duplicates are a major problem for your budget.

While manual deduplication is time-consuming and impractical, leaving the issue unaddressed will impact analytics, campaign efficiency, and ultimately, your bottom line.

Fortunately, the Marketo API solves this directly by allowing us to perform cost-effective, mass deduplication of leads.

Here’s a step-by-step guide on how it’s done!

(This guide is for those with a foundational understanding of the Marketo API and is designed for Marketo users. If you want to learn more about the Marketo API, check out our API webinar and an extensive API course.)

pink line

1. Extract Duplicates from Marketo Using a List Export

The first step in the deduplication process is to identify and extract the duplicate leads from your Marketo instance.

In Marketo, create a Smart List that identifies duplicate leads based on your chosen criteria (e.g., email address). Once your Smart List is populated, select all the leads and export them to a CSV file. You should have something similar to the screenshot below before you export.

This exported list will serve as your reference for the deduplication process (and provide a backup in case of any issues.)
 

2. Define Your Winner Criteria and Deduplication Rules

Before we start merging leads, it’s crucial to establish clear rules for determining which lead will be the “winner” (the consolidated lead that will remain after merging several duplicates). We must also define rules on how to handle conflicting data.

In our case, we want the oldest lead to be chosen as the winner to preserve the original acquisition date. But at the same time, we want to maintain paid media as the lead source.

Feel free to define your rules and criteria as needed – you may want to maintain the most recent phone number, job title, subscription status, and other characteristics as well.
 

3. Deduplicate Leads Based on the Winner Criteria

By now, we should have an exported list of duplicates and a winner criterion. The next step is to perform mass deduplication through the Marketo API (learn more about accessing the Marketo API here) using the following Python script:

deduplicate:def deduplicate(winner,losers):
    access_token=get_access_token()
    url = f"{BASE_URL}/rest/v1/leads/{winner}/merge.json"
    headers={
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"}
    params = {
        "leadIds": losers
    }
    response = requests.post(url, params=params, headers=headers)
    return(response.json())

 
This will examine groups of duplicate leads, determine the winner based on your criteria, and merge the leads using the Marketo API.
 

4. Update the Winner Lead with Data from the Losing Leads

After merging, we need to ensure that any data we want to keep from “losing” leads (such as paid media as a source) is consolidated into the single “winner”.

Here’s a Python script that will update the winner based on our deduplication rules:

def update_lead(leadid,field,value):
	access_token=get_access_token()
	url=f"{BASE_URL}/rest/v1/leads.json"
	headers={
    	"Authorization": f"Bearer {access_token}",
    	"content-type": "application/json"
	}
	params={
    	'action': 'updateOnly',
    	'lookupField': 'id',
    	'input':[{
        	'id': leadid,
        	field: value
    	}]}
	response=requests.post(url=url,data=json.dumps(params), headers=headers)
	print(response.json()['result'])

 
The last thing we need to do is run a Python script that will execute all these functions together (prioritizing the oldest lead as the winner and paid media lead source):

df_aux=df[df['Email Address']==email]
    leads=list(df_aux['Id'])
    winner=min(leads)
    leads.remove(winner)
    deduplicate(winner,str(leads)[1:len(str(leads))-1])
    if (df_aux['Lead Source']=='Paid Media').sum()>0:
        update_lead(winner, 'LeadSource', 'Paid Media')

 
And that’s it! Now, all of our duplicates have successfully been merged with data from our deduplication rules preserved for each one.

pink line

By taking advantage of the Marketo API to implement an efficient deduplication process for your Marketo database, you’ll be maintaining good data hygiene, which improves marketing effectiveness and leads to direct cost savings.

And while this guide provides a solid foundation for deduplication, every organization’s needs are unique. You may need to adjust the winner criteria and deduplication rules to best suit your specific requirements.

If you need help implementing this deduplication process or have questions about optimizing your Marketo instance, book a 30-minute chat with us here!

Marketo APIs: 3 Easy Ways to Activate Your Data

By taking advantage of the Marketo API:

Marketers unlock a gold mine of data that can support overall strategy in a major way.

But this can be intimidating for folks who haven’t used the API before.

This is why we decided to present:

“Marketo APIs: 3 Easy Ways to Activate Your Data”.

Our goal with this event was to make the Marketo APIs more accessible for marketers and demonstrate easy use cases that add a ton of value.

Hosted by: Lucas Machado (Director of AI & Automation, RP), Corey Bayless (Director, Prudential Financial), Lauren McCormack (Vice President, RP).

The FULL recording is available  above.

Here’s a brief overview of what we covered.

pink line

After a quick introduction, we started by covering API fundamentals including what APIs are, why you should care, and Markto API basics.

From there, we covered not 3, but 5 Marketo API use cases!

1. Extract Bulk Activity Logs

This is a simple, but very powerful use case. While Marketo allows us to extract individual activity logs, it doesn’t allow us to extract them in bulk. Bulk logs are useful for analyzing email data, uncovering why opportunities were created, and much more. Watch above for a step-by-step walkthrough on how to extract bulk activity logs using the Marketo API.

2. Revert Data Changes

If you’ve ever been in a situation where you uploaded the wrong list to Marketo — or if the data was badly formatted — this will be a lifesaver. In the webinar above, learn how to use the Marketo API to reverse the data changes from a list upload. 

3. Create Programs

Marketo is great at scaling. But there can still be a lot of manual work in the form of cloning programs, updating tokens, activating smart campaigns, and so on. If you’re running an instance with 100 campaigns per day then it will be pretty much impossible to keep track of it all. Fortunately, we cover how the Marketo API can be used to automate many of these manual processes — saving you time and enabling greater consistency and scalability. 

4. Deduplication

Nearly every Marketo instance will eventually harbor duplicate leads. They can come from list uploads, form fills, CRM syncs, manual lead creation, etc. And since Marketo subscription costs scale with database size, duplicates are a major problem. Fixing them manually isn’t realistic either simply because of how long it takes. The Marketo API solves this directly by allowing you to perform mass deduplication in your instance. 

5. Data Pipelines

Our final application uses the Marketo API to import outside data into static lists within your Marketo instance. This is extremely useful because not all SaaS platforms have code-free integration with Marketo. The API offers users a way to get data from those platforms (such as Oracle or Snowflake) into their instance without a ton of time-consuming manual coding work to keep Marketo lists up to date. 

pink line

Be sure to check out the webinar recording above for an in-depth demonstration of how to apply these use cases.

And if you have any questions about the Marketo API, don’t hesitate to reach out to us!

 

 

AI + Marketo: How to Implement 3 High Impact, No Risk Solutions

Whenever AI is mentioned in the workplace, there are normally concerns over data privacy, security, and compliance (and rightfully so).

So, how can marketers safely integrate AI into their work?

We answered this question by showcasing 3 AI use cases that protect your data, while still producing high-impact results.

It all happened last week in our event titled: “AI + Marketo: How to Implement 3 High Impact, No Risk Solutions”.

Hosted by: Andy Caron (President, RP), Lucas Machado (Director of AI & Automation, RP), and Tyron Pretorius (Owner, The Workflow Pro).

If you missed it, you can watch the FULL recording above!

Here’s a quick overview of what we covered.

pink line

Before we get into the specific use cases, we went through a few “AI Fundamentals” including the differences between general models and fine-tuned models, pricing, and compliance.

Then, we went deep on the ChatGPT-Marketo connection, including the use of webhooks, integration platforms, and the Marketo API.

After that, we covered 3 specific use cases (with a bonus use case at the end):
 

1. Sentiment Analysis

For this, we demonstrate how to perform a sentiment analysis of your Marketo emails using ChatGPT, leading to enhanced content that resonates with your audience and improves open rates, click-through rates, and conversions.

Follow along with the webinar or read our in-depth guide here.
 

2. Finding the Best Email Send Times

Here, we show how you can extract email interaction data from your Marketo instance and use ChatGPT analysis to answer the age-old question: When is the best time to send emails?
Follow along with the webinar or read our in-depth guide here.
 

3. Persona Classification

Traditional classification methods often fall short due to constantly changing job titles, industry terms, and other parameters. The good news is, we can create our own fine-tuned GPT that understands the patterns of these term changes, then integrate directly into Marketo for enhanced persona classification.

Follow along with the webinar or read our in-depth guide here to learn how it’s done.
 

4. Sales Acceleration (BONUS)

For our final use case, we show you how to integrate ChatGPT, Marketo, and your CRM with an IPaaS solution like Zapier or Workato to automatically generate reports for your sales team – instantly contextualizing MQLs so your reps can have effective conversations that close more sales.

Follow along with the webinar or read our in-depth guide here.

pink line

If you have any questions about integrating AI with Marketo, don’t hesitate to reach out to us!

How to Accelerate Sales with GPT

In this guide, we’ll show you how to integrate ChatGPT, Marketo, and your CRM with an IPaaS solution like Zapier or Workato to automatically generate reports for your sales team, granting them instant insights into MQLs.

Why does this matter?

In sales, context is key. Especially when interpreting how and why a lead has become a Marketing Qualified Lead (MQL).

Yet, too often, the data behind that qualification is buried in layers of engagement metrics, making it very time-consuming for sales reps to decipher and piece together the story on their own.

This solution directly addresses that issue by allowing ChatGPT to analyze lead engagement data and generate a clear, concise summary of their journey toward qualification.

By achieving a deep understanding of each lead’s journey more efficiently, your sales team will always be prepared to have effective and informed conversations that close.

Who is this guide for?

Before we get into the nitty gritty, this guide is designed for those with basic knowledge of Marketo, as well as foundational knowledge in an integration platform of their choice (whether that’s Zapier, Workato, Microsoft Power Automate, etc.)

Let’s get into it!
 

Why IPaaS?

For those who may not know, IPaaS stands for “Integration Platform as a Service”. Integrating ChatGPT with Marketo and our CRM without an IPaaS would’ve involved more manual coding work, AWS, and so on, making this entire process far more tedious.

For that reason, we’ve opted to lean on an integration platform to do some of the heavy lifting. We’re using Zapier, but any other one should get the job done. Your exact IPaaS will likely depend on which one your company has invested in.

And since the terminology, UI, and feature set will differ slightly depending on what you’re using, we’re going to keep this guide IPaaS-agnostic – focusing more on the logic behind the workflow, as well as the code snippets you’ll need at each step.

Here’s a graphic of what the entire workflow will look like at a high level:


 

Step 1: Initial setup in Marketo

Start by creating a “text” field in your Marketo instance and make sure it’s mapped to your CRM for sales team visibility. This is where we’ll house the text summary written by ChatGPT that contextualizes MQLs for sales reps.
 

Step 2: Starting the workflow in your IPaaS

Now, we need to build the workflow that will fill the Marketo text field we just created. Head over to your integration platform and create a new workflow that is triggered by an HTTP request.

This trigger will be our first block in the flow:


 

Step 3: Retrieving data from Marketo

In this step, we’re going to tackle the next three blocks in the workflow:

There are a couple things we need from Marketo to extract lead engagement data that we’ll feed to ChatGPT later.

1) First, we need the Marketo Access Token. This will grant us access to the Marketo API, allowing us to programmatically talk to Marketo to enable the automation of tasks, integrate with other systems, and retrieve data.

Use this code to get the Marketo Access Token:

import requests
import pandas as pd
import json
MUNCHKIN = "EDIT HERE"
client_id = "EDIT HERE"
client_secret= "EDIT HERE"
leadid="EDIT HERE"
sinceDate="EDIT HERE"
gptAPIKey="EDIT HERE"
fieldName="EDIT HERE"
def get_access_token():
    global client_id
    global client_secret
    global MUNCHKIN
    params={'grant_type': 'client_credentials',
            'client_id': client_id,
            'client_secret': client_secret}
    headers={'Accept-Encoding': 'gzip'}
    url="https://"+MUNCHKIN+".mktorest.com/identity/oauth/token"
    response=requests.get(url=url,params=params,headers=headers)
    data=response.json()
    print(data)
    return data['access_token']

 

2) Second, we need the Marketo Paging Token. This is required to use the Activities API, which is used to interact with lead engagement data (opened web pages, attended webinars, etc.) We also use this to define the time frame for pulling engagement data. In Marketo, you can’t select any specific time frame; you can only set a start date (up to 3 months ago) and pull data from there to the present. In our case, we recommend setting that to 1 month ago.

Use this code to get the Marketo Paging Token:

url="https://"+MUNCHKIN+".mktorest.com/rest/v1/activities/pagingtoken.json"
token=get_access_token()
params={'access_token': token,
        'sinceDatetime': sinceDate}
response=requests.get(url=url,params=params)
data=response.json()
nextPageToken=data['nextPageToken']

 

3) Now, we’ll use the two tokens above, plus the lead ID from Step 2, to fetch all the engagement data from a specified back date. This will generate a large string of data that includes all the email interactions, web activity, program status, and more of a lead.

Use this code to fetch lead engagement data:

access_token=get_access_token()
def get_lead_activities(auth_token, lead_id, firstToken):
   url = f"https://"+MUNCHKIN+".mktorest.com/rest/v1/activities.json"
    params = {
        "access_token": auth_token,
        "leadId": lead_id,
        "activityTypeIds": "1,2,3,10,11,34,104",
        "nextPageToken": firstToken
    }
    activities = []
    more_results = True
    while more_results:
        response = requests.get(url, params=params)
        data = response.json()
        if 'result' in data:
            activities.extend(data['result'])
        more_results = data.get('moreResult', False)
        if more_results:
            params["nextPageToken"] = data['nextPageToken']
    return activities
all_activities = get_lead_activities(access_token, leadid,nextPageToken)
all_activities = str(all_activities).replace('"', "'")
activities=all_activities

 

Step 4: Analyze engagement data with ChatGPT

Let’s move on to the final two blocks of the workflow:


 

1) This is where we come up with an appropriate prompt about summarizing how and why a lead became an MQL, then send it to ChatGPT through the GPT-4o API.

Here’s a prompt that produced good results for us:

“Analyze the following lead activities and explain the activities that contributed to this lead being marked as MQL so a salesperson knows how they should approach the client, including which product or service this lead is most interested in and any other relevant insights. Include relevant URLs on form fills:" +activities+" – Remember this will only be read by a salesperson, so don't use technical explanations, just your best summary. Keep your response limited to 100 words.”

 

And use this code to send it to ChatGPT via the API:

def send_to_chatgpt(activities):
    url = "https://api.openai.com/v1/chat/completions"
    headers = {
        "Authorization": gptAPIKey,
        "Content-Type": "application/json"
    }
    prompt = """Analyze the following lead activities and explain the activities that contributed to this lead being marked as MQL so a salesperson knows how they should approach the client, including which product or service this lead is most interested in and any other relevant insights. Include relevant URLs on form fills:""" +activities+""" – Remember this will only be read by a salesperson, so don't use technical explanations, just your best summary. Keep your response limited to 100 words."""
    data = {
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": prompt}],
        "max_tokens": 250
    }
    response = requests.post(url, headers=headers, json=data)
    return response.json()
gpt_response = send_to_chatgpt(activities)['choices'][0]['message']['content']

 

2) Once we’ve prompted GPT, we need to capture the text summary it sends back to us and use an API request to store it in the Marketo text field we created in Step 1.

Use this code to capture and store ChatGPT’s response:

def update_marketo_field(lead_id, field_name, gpt_response):
    url = "https://+MUNCHKIN+.mktorest.com/rest/v1/leads.json?access_token="+str(input_data['access_token'])
    headers = {
        "Content-Type": "application/json"
    }
    payload = {
        "action": "updateOnly",
        "lookupField": "id",
        "input": [
            {
                "id": int(lead_id),
                field_name: gpt_response
            }
        ]
    }
    response = requests.post(url, headers=headers, json=payload)
update_response = update_marketo_field(leadid, fieldName, gpt_response)

 

Step 5: Automate the workflow

In our fifth and final stage, we need to ensure this IPaaS workflow is triggered any time a lead becomes an MQL in our Marketo instance. This is achieved by creating a webhook in Marketo that looks like this:


 

Example response:


 
pink line

And that’s it!

Now, whenever a lead becomes an MQL in Marketo, your IPaaS workflow should be triggered.

This will automatically send a full text summary of why that lead became an MQL to a Marketo text field that is also mapped to your CRM for sales reps to see.

Instant insights into the lead journey will save your sales reps tons of time they’d otherwise spend sifting through metrics to piece together the story.

Ultimately, they’ll be more informed more quickly, so they can have better conversations with prospects and close more sales.

If you need help setting this up or have any other questions, feel free to reach out here.

How to Use GPT for Sentiment Analysis
in Marketo

In this guide, we’ll show you how to perform a sentiment analysis of your Marketo emails using ChatGPT, leading to enhanced content that resonates with your audience and improves open rates, click-through rates, and conversions.

And if you’ve been wondering how to safely integrate AI into your marketing tasks, this is a great starting point that is relatively straightforward to set up.

For those who may not know, sentiment analysis is a natural language processing technique used to determine the emotional tone behind a text. Through text data analysis, this process can identify whether the sentiment expressed is positive, negative, or neutral.

For marketers, a deep understanding of audience sentiment can provide clues about what type of content elicits positive reactions from recipients. By leveraging these insights, you can improve your content strategy and engage your audience more effectively.

This guide is geared towards Marketo users, but if you already have email data – including body text and subject lines – from a different platform exported as a CSV, skip to step 4 to see where ChatGPT comes in.

Let’s get into it!

pink line

Step 1) Export your email performance report from Marketo.

We’ll get things started by navigating over to the “Reports” section in Marketo. We want to export an email performance report of emails that are regularly delivered to the same database – think monthly newsletters, loyalty program updates, seasonal sale events, etc.

By using emails delivered to a similar audience over a longer period, we eliminate as many variables as possible, allowing us to measure how shifts in tone and content change engagement metrics.

We should now have an email performance report exported as a CSV file from Marketo that includes open rates, click-through rates, bounce rates, and several other fields.
 

Step 2) Use the Marketo API to Localize Email IDs

In this step, we’ll be using the Marketo API to add and manipulate some of the information in our CSV file.

Why are we doing this?

In short, for each email we’re isolating the “Email Name” and “Email Program”, then using that information to fetch the “Email ID”. The “Email ID” will then be used in the next step to fetch the subject line and body text of each email, which we’ll then upload to ChatGPT for sentiment analysis.

If this sounds complicated, don’t worry. It’s relatively straightforward once we break it down.

Note: The Marketo API is a way for us to programmatically talk to Marketo to enable the automation of tasks, integrate with other systems, and in our case, retrieve data from the Marketo platform.

1) In our current CSV file, the first column titled “Email Name” has a bunch of consolidated information, including the email name and the email program. The problem is, we need to split this information into two separate, dedicated columns: One for the “Email Name” and one for the “Email Program.”

Use the following code snippets to do this:

Initial Setup

import pandas as pd
import json
import requests
 
base_url = 'https://MUNCHKINID.mktorest.com'
client_id = 'YOUR-CLIENT-ID'
client_secret = 'YOUR-CLIENT-SECRET'
 
def getToken ():
	response = requests.get(base_url+'/identity/oauth/token?grant_type=client_credentials&client_id='+client_id+'&client_secret='+client_secret)
 
	temp = json.loads(response.text)
	token = temp['access_token']
 
	return token
 
df=pd.read_excel('YOUR-FILE-PATH.xlsx')
df.drop(['First Activity (EDT)','Last Activity (EDT)'],axis=1,inplace=True)

 

Get the Program and Email Name

df[['Program','Email']] = df['Email Name'].str.split('.',expand=True)

 

2) Once those are split into two columns, we can perform an API call that will tell Marketo to use “Email Name” and “Email Program” to fetch the “Email ID”.

Use this code snippet to do that:

Get the Email ID

def getProgramID(programName):
	token=getToken()
	response = requests.get(base_url+'/rest/asset/v1/program/byName.json?name='+programName+'&access_token='+token)
	return json.loads(response.text)['result'][0]['id']
 
def getFolder(programID):
	token=getToken()
	response = requests.get(base_url+'/rest/asset/v1/folders.json?root={"id":'+str(programID)+',"type":"Program"}&access_token='+token)
	return json.loads(response.text)['result'][0]['folderId']
 
def getEmails(folderID):
	token=getToken()
	response = requests.get(base_url+'/rest/asset/v1/emails.json?folder='+str(folderID)+'&access_token='+token)
	return json.loads(response.text)['result']
 
def getEmailID(emailName,programName):
	emails=getEmails(getFolder(getProgramID(programName)))
	for email in emails:
    	if email['name']==emailName:
        	return email['id']
 
df['EmailID']=df.apply(lambda x: getEmailID(x.Email, x.Program), axis=1)

 

Step 3) Download Email Subject Lines and Body Text

Now that we have the “Email ID” for each email, we’ll use the Marketo API to download all the subject lines and body text data.

Here are the code snippets you’ll need to do this:

1) Get Email Subject Lines

def getEmailSubject(emailID):
	token=getToken()
	response = requests.get(base_url+'/rest/asset/v1/email/'+str(emailID)+'.json?access_token='+token)
	return json.loads(response.text)['result'][0]['subject']['value']
 
df['EmailSubject']=df.apply(lambda x: getEmailSubject(x.EmailID), axis=1)

 

2) Get Email Body Text

def getEmailText(emailID):
	token=getToken()
	response = requests.get(base_url+'/rest/asset/v1/email/'+str(emailID)+'/fullContent.json?type=Text&access_token='+token)
	return json.loads(response.text)['result'][0]['content']
 
df['EmailText']=df.apply(lambda x: getEmailText(x.EmailID), axis=1)

 

3) Lastly, we must save the final results into an updated CSV file using this code:

df.to_excel(‘YOUR-FILE-PATH.xlsx',index=False)

 

At this point, your CSV file should now have engagement metrics, body text, and subject lines for every email.
 

Step 4) Perform Sentiment Analysis with ChatGPT

This is where the real magic happens!

With our data ready, we can now use ChatGPT to perform a comprehensive sentiment analysis.

ChatGPT-4o can do this because of its enhanced language understanding, improved natural language processing, and advanced data analytics feature that can create code and assess specific parts of data that you upload.

Note: You’ll need a Chat-GPT Plus subscription for 20 USD per month to upload your CSV for sentiment analysis.

1) Go over to ChatGPT in your browser, press the “Attach file” button, and upload your email data CSV.


 

2) Prompt ChatGPT to perform a sentiment analysis. Here’s an example:

You are a Marketing Data Analyst at company X that does X. Most of our audience is X. Your job is to analyze the data from our Marketing emails and answer the following questions:
1. For a sentiment analysis: Which type of subject lines result in a higher open rate? Which type of content leads to a higher click rate?
2. Which words in the subject line result in a higher open rate? Which words in the body content result in a higher click rate? And which words result in a lower open and click rate? Remove the URL-related words.
3. Which topics lead to higher open and click rates? And which topics lead to lower ones?

 

Step 5) Optimize your content

The last step is to apply the trends and insights provided by ChatGPT’s sentiment analysis to improve the effectiveness of your content.

ChatGPT does a pretty good job of contextualizing sentiment scores by explaining parameters and categories clearly, so the interpretation process should be relatively straightforward – but ultimately, it’s up to you and your team to tailor and refine your email subject lines and body content accordingly.

It’s also important to constantly measure and update your content strategy, as well as reanalyze sentiment with ChatGPT as new data and feedback come in.

pink line

Leveraging ChatGPT for email sentiment analysis is a perfect starting point for anyone looking to take advantage of AI to improve their content strategy.

You’ll gain instant insights into what kind of messaging and tone is resonating with your audience effectively, and where you need to change things up to improve engagement.

Remember to regularly reassess your content with fresh data and sentiment analysis to stay aligned with your audience’s evolving preferences – view this process as one of continuous refinement over time.

If you need help setting this up, or if you want to learn about other ways we’re using AI to enhance marketing strategies, send us a message here.

How to Use GPT
for Persona Classification in Marketo

In this guide, we’ll show you exactly how to create a fine-tuned GPT model that’s integrated directly into Marketo for enhanced persona classification.
 
Persona classification plays a crucial role in successfully delivering targeted and personalized content to your audience.
 
However, traditional classification methods often fall short due to the dynamic nature of job titles, industry terms, and other parameters.
 
For example, Persona A may include a job title with the word “Tech”. Then, some months or even years later, that same job title drops “Tech” and uses “IT” in the title instead. This can be true for several different job titles and even entire industries.
 
All these words and terms must be constantly updated for your personas to accurately reflect the roles you want to target – and this takes a lot of manual work.
 
Put simply, marketers spend a lot of time defining personas only for them to quickly become outdated.
 

This is where GPT comes in

The good news is, we can create our own fine-tuned GPT that understands the patterns of these term changes.

It can take “Technology Analyst” and “IT Analyst” and feed them into the same group, for example. Then, when a new term like “Python” comes up in a job title, it’ll understand where to categorize that role based on your existing persona instructions and examples.

And since we’ll be training our model on job titles and industry terms rather than actual private identifiers, this application of GPT has no privacy or compliance risks whatsoever.

Here’s our guide on how to set it up!

(This guide is for tech professionals and enthusiasts who use Marketo. Not a lot of coding is required, but it would help to know coding basics or be willing to learn!)
 

Understanding persona classification

Before we get into the technical aspects of tuning your GPT model and integrating it with Marketo:

None of this will be very useful if you haven’t already taken the time to define your personas.

This almost goes without saying, but we still wanted to quickly mention it.

Defined persona groups based on job title, industry, pain points, and other characteristics are information that your fine-tuned GPT will need in order to automatically update and recategorize contacts when terms change.
 

1) Prepare your data for GPT fine-tuning

The first thing we need to do is prepare our data for fine-tuning. Let’s walk through what that looks like.

  1. Start by reaching out to your Marketing and Sales teams and gather about 200 leads/customers that will be used as examples for a given persona. The job titles, industries, and other important characteristics of these contacts need to fit your previously defined persona as closely as possible.
  2. Once you have those contacts, it’s time to clean the data. Eliminate any duplicate entries, weird characters, or other erroneous inputs.
  3. Now, we need to transform this data into a JSONL format (for those who may not know, this is a JSON but without any commas). This will allow us to feed it into our custom GPT with instructions and descriptions about persona classification. Since this step is very important, we’ve created a resource that will help you through it. Follow the guide below:

How to convert your data to JSONL format

  1. Open up this JSONL formatting tool we created and create a copy for yourself to edit.
  2. The “System” column is where our instructions for GPT go. The message can be something like: “You are going to analyze lead job titles to fit them into the correct persona. I’ll send you the job title only, and you should respond with the persona classification only.”
  3. In the “User” column, input the job titles of each of your contacts. In our example, we’ve put “Cloud Infrastructure Analyst” as the job title.
  4. In the “Assistant” column, we are going to input the persona “type” that we want GPT to give us. In other words, when it receives the job title from the “User” column, we want it to categorize that as “Persona A” or simply “A”. Here is an example of what your first row should look like at this point:

     

  5.  

  6. From here, you can repeat the same “System” column message for every single row. Then copy and paste the rest of the job titles from your contacts in the “User” column, and “A”, “B”, “C”, etc. for the corresponding persona type as your output in every row of the “Assistant” column. You don’t need to touch anything in the “JSONL” column, as this has been set up to automatically populate based on the inputs from the other columns.
  7. Once all your data is in there, we need to get it out of the sheet and into a .txt file. Simply copy and paste everything in the JSONL column and paste that into your .txt file.

Important note: Take 80% of your data (if you have 600 rows, then take 480 rows) and put that into one .txt file, then take the remaining 20% of your data (120 rows) and paste those into a second .txt file. We do this because we want two separate JSONLs: One for training (80% of our data) and one for testing (20% of our data).

We do this because GPT will not only train itself on the larger file but will also optimize itself using the test file as a reference – leading to better performance and results.

 

2) Creating a fine-tuned GPT model

Now that our data is cleaned and formatted into 2 JSONL files (one for training, one for testing), we can send it to the OpenAI API to fine-tune our GPT model.

If you want, you can check out OpenAI’s extensive tutorial on how to create a fine-tuned model here. But we will quickly walk you through the basic, high-level steps.

  1. When you start the process of fine-tuning a model through the OpenAI SDK, use a snippet of Python code to upload your JSONL training file like this:
  2. import openai
    openai.api_key = ""
    openai.File.create(
      file=open(r"train_file_path", "rb"),
      purpose='fine-tune'
    )
    

     

  3. Do this again, but now upload your JSONL testing file.
  4. openai.File.create(
      file=open(r"test_file_path", "rb"),
      purpose='fine-tune'
    )
    

     

  5. Check that both files were uploaded and processed successfully using the command “openai.file.retrieve” to check their status.
  6. openai.File.retrieve("Train-File-ID"),openai.File.retrieve("Test-File-ID")
    

     

  7. Now, we can actually fine-tune the model using the code below. Here, GPT will optimize itself by measuring the training file against the test file reference.
  8. openai.FineTuningJob.create(training_file="Train-File-ID", validation_file= "Test-File-ID", model="gpt-3.5-turbo or gpt-4o-mini")
    

     

  9. Lastly, we can confirm that the model is fine-tuned. This is also the step where we receive the fine-tuned model ID, which we will use in our webhook in Marketo. You can also take it upon yourself to test your model before committing it to Marketo using this line of code:
  10. openai.FineTuningJob.retrieve("FT-ID")
    completion = openai.ChatCompletion.create(
      model="MODEL_ID",
      temperature=0,
      max_tokens=100,
      messages=[
        {"role": "user", "content": "Your Test Message"}
      ]
    )
    print(completion.choices[0])
    

     

Note: When creating a fine-tuned model, we are currently limited to GPT 3.5 turbo and GPT4o Mini.
 

3) Integrate your fine-tuned GPT model with Marketo

Our fine-tuned GPT model is now ready to be integrated with Marketo. This is a relatively short step that involves creating a webhook in Marketo (which we covered in Step 4 of this guide) with the following fields:
 

 

4) Integrate your fine-tuned GPT model with Marketo

So we have our fine-tuned GPT model set up (Step 2) and we have our webhook in Marketo created (Step 3). Now we’ll set up some automation in Marketo to use them together.

We’ll do this by creating a smart campaign in Marketo that will be triggered when a new lead is created or when lead information changes.

Once triggered, the smart campaign will send the information via webhook to the fine-tuned GPT, which will respond with the correct persona type (A, B, C, or whatever signifiers you used in your JSONL files).

Finally, if the persona for that lead has changed, the lead record will be automatically updated with the new classification.

Smart List:

 

Flow:

 

Outcome:

 

The Result

When all of this is set up properly, you will have an automatically updating field in Marketo for each lead that will signify which persona they fit into.

  • Here’s a quick example that demonstrates how this new setup will operate:
    • Jim is an “IT Analyst” and has been classified as Persona A.
    • Jim’s role changes to “Technology Analyst”. This new role information could’ve come from a new form Jim filled out, a salesperson on your team updating Jim’s information, etc.
    • Your smart campaign in Marketo is triggered (the one from Step 4).
    • This will call on your fine-tuned GPT model and ask it something like “Which persona is Tech Analyst?” It will respond with Persona A or whichever persona is most appropriate.
    • Then, the Marketo field for Jim’s persona will be automatically updated.

Note: This entire process is not limited to the language you are working in either. It can apply to any language worldwide.

pink line

The upfront work required to set this up is definitely worth it in the long run.

By leveraging a fine-tuned GPT model with proper integration and automation in Marketo, your persona classifications will be far more accurate and up to date, with minimal manual intervention required.

Ultimately, this will improve the effectiveness of your campaigns through better targeting, while freeing up more time for strategic and creative thinking.

And if you need help setting this up or have any other questions about how AI can improve marketing operations efficiency, send us a message here!