Beispiel #1
0
def get_mgid_widget_clicks_and_costs_by_campaign(token, campaign_id,
                                                 start_date, end_date):
    try:
        url = f"https://api.mgid.com/v1/goodhits/campaigns/{campaign_id}/quality-analysis?token={token}&campaignId={campaign_id}&dateInterval=interval&startDate={start_date}&endDate={end_date}"
        response = requests.get(url)
        if response.status_code == 401:
            mgid_token = get_and_return_new_mgid_token()
            return get_mgid_widget_clicks_and_costs_by_campaign(
                mgid_token, campaign_id, start_date, end_date)

        response.raise_for_status()
        response = response.json()
        # The logic below esstenially loops through each each widget and records
        # clicks into my dictionary of widgets. The only complication is if a widget
        # has sources, which are like child widgets. Sources are kept in a list.
        # For each source, if it is "0", that means it is really the parent widget,
        # and its data will be stored in voluum as such. If the source is not "0",
        # then it really is a child widget and its data is stored in voluum as
        # parent widget id + s + child widget id.
        # The reason why it matters how it is stored in voluum is because the
        # purpose of this function is to contribute to getting accurate widget
        # data. Mgid provides accurate data on clicks and cost and voluum provides
        # accurate data on the rest (conversions, revenue, etc).
        widgets_data = {}
        if response[campaign_id][start_date + "_" + end_date] == []:
            return widgets_data
        for id, data in response[campaign_id][start_date + "_" +
                                              end_date].items():
            widget_id = id
            if data["sources"]:
                for source_id, source_data in data["sources"].items():
                    if source_id is not "0":
                        widget_id = f"{id}s{source_id}"
                    widgets_data[widget_id] = {
                        "widget_id": widget_id,
                        "clicks": source_data["clicks"],
                        "cost": source_data["spent"],
                        "coeff": source_data["qualityFactor"]
                    }
            else:
                widgets_data[widget_id] = {
                    "widget_id": widget_id,
                    "clicks": data["clicks"],
                    "cost": data["spent"],
                    "coeff": data["qualityFactor"]
                }

        return widgets_data
    except requests.exceptions.RequestException as e:
        print("Failed - get_mgid_widget_clicks_and_costs_by_campaign")
        send_email(
            "*****@*****.**",
            "Failed - get_mgid_widget_clicks_and_costs_by_campaign() at " +
            str(datetime.now().strftime("%Y-%m-%d %H:%M")), e)
        sys.exit()
Beispiel #2
0
def check_all_mgid_ads(token):
    request_number = 0
    ads_data = {}
    while len(ads_data) == request_number * 700:
        url = f"https://api.mgid.com/v1/goodhits/clients/{mgid_client_id}/teasers?token={token}&limit=700&start={request_number * 700}"
        request_number = request_number + 1
        res = requests.get(url)
        if res.status_code == 401:
            mgid_token = get_and_return_new_mgid_token()
            return check_all_mgid_ads(mgid_token)
        res.raise_for_status()
        res = res.json()
        if len(res) == 0:
            break
        for ad_id in res:
            ads_data[ad_id] = res[ad_id]

    ad_status_counts = {"active": 0, "paused": 0, "pending": 0, "rejected": 0}
    rejected_ads = {}
    for ad_id in ads_data:
        if (ads_data[ad_id]["status"]["code"] == 'goodPerformance'):
            ad_status_counts["active"] += 1
        elif (ads_data[ad_id]["status"]["code"] == 'new'):
            ad_status_counts["active"] += 1
        elif (ads_data[ad_id]["status"]["code"] == 'campaignBlocked'):
            ad_status_counts["paused"] += 1
        elif (ads_data[ad_id]["status"]["code"] == 'blocked'):
            ad_status_counts["paused"] += 1
        elif (ads_data[ad_id]["status"]["code"] == 'onModeration'):
            ad_status_counts["pending"] += 1
        else:
            ad_status_counts["rejected"] += 1
            rejected_ads[ad_id] = {
                "ad_id": ad_id,
                "campaign_id": ads_data[ad_id]["campaignId"]
            }

    subject = f"ok - {len(ads_data)} ads: {ad_status_counts['active']} active, {ad_status_counts['paused']} paused, {ad_status_counts['pending']} pending, {ad_status_counts['rejected']} rejected"
    body = f"{ad_status_counts['active']} of {len(ads_data)} ads in all campaigns are active.\n{ad_status_counts['paused']} of {len(ads_data)} ads in all campaigns are paused.\n{ad_status_counts['pending']} of {len(ads_data)} ads in all campaigns are pending.\n{ad_status_counts['rejected']} of {len(ads_data)} ads in all campaigns are rejected."
    if ad_status_counts["rejected"] > 0:
        subject = f"ALERT - {len(ads_data)} ads: {ad_status_counts['active']} active, {ad_status_counts['paused']} paused, {ad_status_counts['pending']} pending, {ad_status_counts['rejected']} rejected"
        for ad_id in rejected_ads:
            body += f'\n\nad {rejected_ads[ad_id]["ad_id"]} rejected in campaign {rejected_ads[ad_id]["campaign_id"]}\nhttps://dashboard.mgid.com/advertisers/teasers-goods/campaign_id/{rejected_ads[ad_id]["campaign_id"]}'
    print(subject)
    print(body)
    send_email("*****@*****.**", subject, body)
    send_email("*****@*****.**", subject, body)
def get_mgid_campaign_costs(token, client_id, start, end):
    try:
        res = requests.get(
            f"https://api.mgid.com/v1/goodhits/clients/{client_id}/campaigns-stat?token={token}&dateInterval=interval&startDate={start}&endDate={end}"
        )
        if res.status_code == 401:
            mgid_token = get_and_return_new_mgid_token()
            return get_mgid_campaign_costs(mgid_token, client_id, start, end)

        res.raise_for_status()
        return res.json()
    except requests.exceptions.RequestException as e:
        print("Failed - get_mgid_campaign_costs")
        send_email(
            "*****@*****.**",
            "Failed -                get_mgid_campaign_costs() at " +
            str(datetime.now().strftime("%Y-%m-%d %H:%M")), e)
        sys.exit()
def get_mgid_daily_stats_data(token, start_date, end_date):
    mgid_url = f"https://api.mgid.com/v1/goodhits/clients/{mgid_client_id}/campaigns-stat?token={token}&dateInterval=interval&startDate={start_date}&endDate={end_date}"

    try:
        res = requests.get(mgid_url)
        if res.status_code == 401:
            mgid_token = get_and_return_new_mgid_token()
            return get_mgid_daily_stats_data(mgid_token, start_date, end_date)

        res.raise_for_status()
        return res.json()["campaigns-stat"]

    except requests.exceptions.RequestException as e:
        send_email(
            "*****@*****.**",
            "Failed - get_mgid_daily_stats_data at " +
            str(datetime.now().strftime("%Y-%m-%d %H:%M")), e)
        sys.exit()
def get_mgid_included_widgets_by_campaign(token, campaign_id, start_date,
                                          end_date):
    try:
        url = f"https://api.mgid.com/v1/goodhits/campaigns/{campaign_id}/quality-analysis?token={token}&campaignId={campaign_id}&dateInterval=interval&startDate={start_date}&endDate={end_date}"
        response = requests.get(url)
        if response.status_code == 401:
            mgid_token = get_and_return_new_mgid_token()
            return get_mgid_included_widgets_by_campaign(
                mgid_token, campaign_id, start_date, end_date)

        response.raise_for_status()
        response = response.json()

        widgets = []
        if response[campaign_id][start_date + "_" + end_date] == []:
            return widgets
        for id, data in response[campaign_id][start_date + "_" +
                                              end_date].items():
            widget_id = id
            widgets.append(widget_id)
            if data["sources"]:
                for source_id, source_data in data["sources"].items():
                    if source_id is not "0":
                        widget_id = f"{id}s{source_id}"
                        widgets.append(widget_id)

        excluded_widgets = get_mgid_excluded_widgets_by_campaign(
            token, mgid_client_id, campaign_id)
        included_widgets = []
        for widget in widgets:
            if widget not in excluded_widgets:
                included_widgets.append(widget)

        return included_widgets
    except:
        print("Failed - email sent")
        send_email("*****@*****.**",
                   "Failed - get_mgid_included_widgets_by_campaign()",
                   "Failed - get_mgid_included_widgets_by_campaign()")
        sys.exit()
def get_mgid_excluded_widgets_by_campaign(mgid_token, mgid_client_id,
                                          mgid_campaign_id):
    url = f"https://api.mgid.com/v1/goodhits/clients/{mgid_client_id}/campaigns/{mgid_campaign_id}?token={mgid_token}"
    try:
        response = requests.get(url)
        if response.status_code == 401:
            new_mgid_token = get_and_return_new_mgid_token()
            return get_mgid_excluded_widgets_by_campaign(
                new_mgid_token, mgid_client_id, mgid_campaign_id)

        response.raise_for_status()
        response = response.json()
        # the response is a dictionary of lists. The keys are widget ids.
        # The values are sources. If a widget id has a source, it must be
        # this concatenation is necessary {widget_id}s{source_id}.
        # One strange thing about the response is that the source id appears
        # to be in a list but the [] are actually just part of the source id
        # string.
        excluded_widgets = []
        if response["widgetsFilterUid"]["widgets"] == []:
            return excluded_widgets
        for key, value in response["widgetsFilterUid"]["widgets"].items():
            if (value == "[]") | (value == None):
                excluded_widgets.append(key)
            else:
                value = value.replace("[", "")
                value = value.replace("]", "")
                value = value.replace(",", "")
                c_widgets = value.split(" ")
                for c_widget in c_widgets:
                    excluded_widgets.append(f"{key}s{c_widget}")
        # excluded_widgets is a list of excluded widget ids
        return excluded_widgets
    except requests.exceptions.RequestException as e:
        print("Failed - get_mgid_excluded_widgets_by_campaign")
        send_email(
            "*****@*****.**",
            "Failed - get_mgid_excluded_widgets_by_campaign() at " +
            str(datetime.now().strftime("%Y-%m-%d %H:%M")), e)
        sys.exit()
Beispiel #7
0
def exclude_campaign_for_one_p_or_c_widget(token, client_id, widget_id,
                                           campaign_id):
    url = f"https://api.mgid.com/v1/goodhits/clients/{client_id}/campaigns/{campaign_id}?token={token}"
    res = requests.patch(
        url,
        headers={
            "Content-Type": "application/x-www-form-urlencoded",
            "Cache-Control": "no-cache"
        },
        data={"widgetsFilterUid": f"include,except,{widget_id}"})
    # 1/29/19 use the line below when you want to "include". I know it says
    # "exclude, except, widget_id", but this comment is correct, use the
    # line below if you want to include a campaign rather than exclude
    # it. Use the line above if you want to exclude a campaign.
    # data = {"widgetsFilterUid": f"exclude,except,{widget_id}"})
    if res.status_code == 401:
        mgid_token = get_and_return_new_mgid_token()
        return exclude_campaign_for_one_p_or_c_widget(mgid_token, client_id,
                                                      widget_id, campaign_id)
    res.raise_for_status()
    res = res.json()
    # if successful, this function returns json that looks like this
    # {id: campaign_id}
    return json.dumps(res)
def get_mgid_ads_data(token, mgid_client_id):
    try:
        # ads_data is a dictionary of ad ids. Each ad id is unique. The value of
        # each ad id is a dictionary of data for that ad, such as its id and image
        # name. All data retrieved is independent on a time period.

        # The data need to be retrieved with multiple requests because mgid limits
        # each request to 1000 responses. For example, if there are 1050 ads, 2
        # requests are needed - the first request gets 1000 and the second gets 50.
        # The need for multiple requests is handled by a while loop.
        request_number = 0
        ads_data = {}
        while len(ads_data) == request_number * 700:
            url = f"https://api.mgid.com/v1/goodhits/clients/{mgid_client_id}/teasers?token={token}&limit=700&start={request_number * 700}"
            request_number = request_number + 1
            res = requests.get(url)
            if res.status_code == 401:
                mgid_token = get_and_return_new_mgid_token()
                return get_mgid_ads_data(mgid_token, mgid_client_id)
            res.raise_for_status()
            res = res.json()
            # The response is a dictionary of ad ids. Each ad is a dictionary
            # that includes a bunch of data. My dictionary called ads_data will
            # have the same basic structure, except the data for each ad id will be
            # modified and customized.

            # in rare situations the response could be empty. If so, it means there
            # are no more ads to get. Breaking out of the while loop will cause the
            # while condition to no longer be met, which makes sense because all
            # the ad data has been retrieved.
            if len(res) == 0:
                break

            for ad in res.values():
                # extract data and put into variables
                ad_id = str(ad["id"])
                campaign_id = str(ad["campaignId"])
                clicks = ad["statistics"]["clicks"]
                cost = ad["statistics"]["spent"]
                imps = ad["statistics"]["hits"]
                if imps == 0:
                    ctr = 0
                else:
                    ctr = clicks / imps
                url = ad["url"]
                status = ad["status"]["code"]
                # extract image name from the url using regex
                pattern = re.compile(r'(&img=)([^&]*)')
                res = pattern.findall(url)
                image = res[0][1]
                # add an ad to ads_data
                # ads_data is a dictionary of ad ids. Each ad id is a dictionary of data
                # for that ad.
                ads_data[ad_id] = {}
                # fill in the data for a particular ad.
                ads_data[ad_id]["ad_id"] = ad_id
                ads_data[ad_id]["mgid_id"] = campaign_id
                ads_data[ad_id]["clicks"] = clicks
                ads_data[ad_id]["cost"] = cost
                ads_data[ad_id]["imps"] = imps
                ads_data[ad_id]["ctr"] = ctr
                ads_data[ad_id]["url"] = url
                ads_data[ad_id]["image"] = image
                if status == "goodPerformance":
                    ads_data[ad_id]["status"] = "active"
                elif status == "onModeration":
                    ads_data[ad_id]["status"] = "pending"
                elif status == "rejected":
                    ads_data[ad_id]["status"] = "rejected"
                else:
                    # I believe this is from status = blocked or status =
                    # campaignBlocked
                    ads_data[ad_id]["status"] = "paused"

        return ads_data
    except requests.exceptions.RequestException as e:
        print("Failed - get_mgid_ads_data")
        send_email(
            "*****@*****.**", "Failed - get_mgid_ads_data() at " +
            str(datetime.now().strftime("%Y-%m-%d %H:%M")), e)
        sys.exit()