Skip to content

Instantly share code, notes, and snippets.

@evandandrea
Created October 11, 2018 17:09
Show Gist options
  • Save evandandrea/0211ca01036b8fae178e23b4fd61e5bb to your computer and use it in GitHub Desktop.
Save evandandrea/0211ca01036b8fae178e23b4fd61e5bb to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import requests
import urllib
import sys
import os
import argparse
import datetime
import json
ISO8601 = "%Y-%m-%dT%H:%M:%SZ"
def get_marketo_access_token(config):
url = urllib.parse.urljoin(config.marketo_root, '/identity/oauth/token')
params = {
'grant_type': 'client_credentials',
'client_id': config.marketo_client_id,
'client_secret': config.marketo_secret,
}
url += '?' + urllib.parse.urlencode(params)
response = requests.get(url)
response.raise_for_status()
return response.json()['access_token']
def get_paging_token(config, token, since):
url = urllib.parse.urljoin(
config.marketo_root,
'/rest/v1/activities/pagingtoken.json'
)
params = {
'access_token': token,
'sinceDatetime': since.isoformat() + 'Z',
}
url += '?' + urllib.parse.urlencode(params)
response = requests.get(url)
response.raise_for_status()
return response.json()['nextPageToken']
def get_activities(config, token, activity_type_ids, asset_ids, page_token):
url = urllib.parse.urljoin(
config.marketo_root,
'/rest/v1/activities.json'
)
params = {
'access_token': token,
'activityTypeIds': ','.join(activity_type_ids),
'assetIds': ','.join(asset_ids),
'nextPageToken': page_token,
}
response = requests.get(url + '?' + urllib.parse.urlencode(params))
response.raise_for_status()
obj = response.json()
try:
results = obj['result']
except KeyError:
results = []
while True:
if obj['moreResult'] and obj['nextPageToken']:
params['nextPageToken'] = obj['nextPageToken']
response = requests.get(url + '?' + urllib.parse.urlencode(params))
response.raise_for_status()
obj = response.json()
try:
results += obj['result']
except KeyError:
# https://nation.marketo.com/thread/45451-get-activities-doesnt-show-results
pass
else:
break
return results
def get_snap_objects(config, token, store_account_id):
params = {
'filterType': 'snapStoreAccountID',
'filterValues': store_account_id,
'access_token': token
}
url = config.marketo_root + '/rest/v1/customobjects/snap_c.json/?'
url = url + urllib.parse.urlencode(params)
response = requests.get(url)
return response.json()['result']
def get_lead(config, token, lead_id, fields=None):
params = {
'access_token': token,
}
if fields:
params['fields'] = ','.join(fields)
url = config.marketo_root + '/rest/v1/lead/{}.json'.format(lead_id)
params = urllib.parse.urlencode(params)
response = requests.get(url + '?' + params)
return response.json()['result'][0]
def get_leads_with_activity_before_date(config, token, activity_type, activity_asset, page_token, date):
'''activity_type: The Marketo identifier for the type of activity. For
example, 10 is "Open Email".
activity_asset: The target of that activity. For example, 7099 is the
"Thanks for checking out Snapcraft" email.
page_token: A Marketo token specifically for pagination.
date: Activities ocurring after this date will be ignored.
'''
activity_type_ids = [activity_type]
asset_ids = [activity_asset]
leads = []
for obj in get_activities(config, token, activity_type_ids, asset_ids, page_token):
activity_date = datetime.datetime.strptime(obj['activityDate'], ISO8601).date()
if activity_date <= date:
leads.append((obj['leadId'], activity_date))
return leads
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('date', metavar='YYYY-MM-DD', nargs='?')
parser.add_argument('--marketo-root', required=True)
parser.add_argument('--marketo-secret', required=True)
parser.add_argument('--marketo-client-id', required=True)
config = parser.parse_args(sys.argv[1:])
if config.date:
start = datetime.datetime.strptime(config.date, '%Y-%m-%d')
else:
start = datetime.date.today() - datetime.timedelta(days=1)
token = get_marketo_access_token(config)
two_weeks_prior = start - datetime.timedelta(days=14)
one_week_prior = start - datetime.timedelta(days=7)
page_token = get_paging_token(config, token, two_weeks_prior)
# Email 1
# 7099: Thanks for checking out Snapcraft
leads = get_leads_with_activity_before_date(
config, token, '10', '7099', page_token, one_week_prior
)
succeeded = 0
for lead_id, mail_date in leads:
lead = get_lead(config, token, lead_id, fields=['snapStoreAccountID'])
store_account_id = lead['snapStoreAccountID']
snaps = get_snap_objects(config, token, store_account_id)
for snap in snaps:
created_at = snap['createdAt']
created_date = datetime.datetime.strptime(created_at, ISO8601).date()
if created_date - mail_date <= datetime.timedelta(days=7):
succeeded += 1
break
print('In the week starting {}:'.format(two_weeks_prior))
msg = 'Read "Thanks for checking out Snapcraft": {}'
print(msg.format(len(leads)))
msg = 'Pushed a snap within 7 days of reading the mail: {} ({:.2f}%)'
if succeeded > 0:
percent = succeeded/len(leads)*100
else:
percent = 0
print(msg.format(succeeded, percent))
# Email 2
# 7103: Ready to reach a wider audience?
leads = get_leads_with_activity_before_date(
config, token, '10', '7103', page_token, one_week_prior
)
succeeded = 0
for lead_id, mail_date in leads:
lead = get_lead(config, token, lead_id, fields=['snapStoreAccountID'])
store_account_id = lead['snapStoreAccountID']
snaps = get_snap_objects(config, token, store_account_id)
for snap in snaps:
if snap['mostStableChannelReached'] == 'stable':
# FIXME this doesn't carry the date stable was reached.
# Could have happened at any time since.
# Could backfill from release history.
succeeded += 1
break
print('In the week starting {}:'.format(two_weeks_prior))
msg = 'Read "Ready to reach a wider audience?": {}'
print(msg.format(len(leads)))
msg = 'Released to stable within 7 days of reading the mail: {} ({:.2f}%)'
if succeeded > 0:
percent = succeeded/len(leads)*100
else:
percent = 0
print(msg.format(succeeded, percent))
# Email 3
# 7038: Make snap pop
leads = get_leads_with_activity_before_date(
config, token, '10', '7038', page_token, one_week_prior
)
succeeded = 0
for lead_id, mail_date in leads:
lead = get_lead(config, token, lead_id, fields=['snapStoreAccountID'])
store_account_id = lead['snapStoreAccountID']
snaps = get_snap_objects(config, token, store_account_id)
for snap in snaps:
if snap['hasCompleteListingDetails']:
# FIXME this doesn't carry the date stable was reached.
# Could have happened at any time since.
# Impossible to backfill; data not currently tracked.
succeeded += 1
break
print('In the week starting {}:'.format(two_weeks_prior))
msg = 'Read "Make snap pop": {}'
print(msg.format(len(leads)))
msg = 'Added details within 7 days of reading the mail: {} ({:.2f}%)'
if succeeded > 0:
percent = succeeded/len(leads)*100
else:
percent = 0
print(msg.format(succeeded, percent))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment