How to get LinkedIn Campaign Analytics Data with Python: A Step-by-Step Tutorial
Hello and welcome! Thank you for visiting. Want to dive deeper into your LinkedIn campaign data? Let’s leverage Python to extract valuable insights directly through the LinkedIn Advertising API. In this step-by-step guide, you’ll learn to develop a Python script to extract reporting data from LinkedIn using API. Specifically, we’ll use the LinkedIn Advertising API to retrieve valuable campaign performance data (Reporting or Analytics data) from your LinkedIn Campaign Manager Account. This data can be leveraged for marketing research, performance analysis, and competitive insights.
With the growing demand for social network integration in applications, extracting data from social channels has become increasingly important. To connect with your LinkedIn Campaign Manager Account, the application must go through an authentication process using OAuth, requiring credentials like Access Token, App ID, App Secret, and Account ID. If you already have these credentials, you’re all set to begin. If not, don’t worry — we’ll guide you through setting up a LinkedIn Developer account and generating the necessary credentials in just three simple steps.

If you’re looking to maximize the potential of LinkedIn API integration, I’m here to help. Whether you have questions, need guidance, or automated token generation solutions, or require tailored consulting services, don’t hesitate to reach out. Let’s discuss how I can assist you in achieving your goals in just no time. Here are the ways you can connect with me, and let’s start a conversation about your unique requirements.
Pulling LinkedIn Campaign Data with Python: Code Structure and Files
Python Code Structure for calling LinkedIn API:
The project consists of the following files:
- ln_main.py
- get_linkedin_data.py
- .env
I’ve developed code that can generate tokens, and extract data at the campaign group, campaign, ads, and creative levels. It efficiently handles pagination, date constraints, and API rate limits, and retrieves a wide range of metrics. If you’d like to get access to the code, feel free to get in touch with me directly on WhatsApp at +91 7892353323. You can also connect with me through LinkedIn or the provided Contact Form.
I’ll be happy to share the script and guide you through the integration process to ensure a smooth setup with your account. This can save you at least 5+ hours of effort, and I can also customize the code to meet your specific requirements.
1. Securely Store Credentials
Store your access token, refresh token, expiry time, and other credentials securely. Ideally, use cloud-based storage solutions like AWS Secrets Manager. Alternatively, store them in a .env file, which is designed to hold environment variables for a project. This method is recommended for this guide. While JSON files can be efficient for credential management, they are less secure and more vulnerable to unauthorized access.
Let’s create a .env file to manage your LinkedIn API credentials.
CLIENT_ID = "<Replace with your API app client ID >" CLIENT_SECRET = "<Replace with your API app client secret >" ACCESS_TOKEN = "<Replace with your API app access token >" ACCOUNT_ID = "<Replace this with LinkedIn ads account ID>"
You can also get the code to extract LinkedIn Marketing account details and campaign reports from my GitHub repo through GitHub Link.
2. Create a main.py Python file
The main.py file serves as the core of your LinkedIn campaign data extraction project, controlling the overall flow. This is the file you’ll execute to run the project. Naming it main.py ensures easy access and management.
#!/usr/local/bin/python3 # command to run this code $ python3 ./main.py -s 2024-06-25 -e 2024-06-25 import getopt import sys import datetime import json import os from dotenv import load_dotenv load_dotenv() from get_linkedin_data import * def readfile(argv): global s_date global e_date try: opts, args = getopt.getopt(argv,"s:e:") except getopt.GetoptError: usage() for opt, arg in opts: if opt == '-s': s_date = arg elif opt == '-e': e_date = arg else: print("Invalid Option in command line") if __name__ == '__main__': try: timestamp = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d : %H:%M') print("DATE : ",timestamp,"\n") print("\n Process start") readfile(sys.argv[1:]) access_token = os.getenv("ACCESS_TOKEN") account_id = os.getenv("ACCOUNT_ID") #call the LinkedIn API query function (i.e get_linkedin_campaign_data) ln_campaign_df = get_campaigns_list(access_token,account_id) print("\n All Campaigns :\n",ln_campaign_df) if not ln_campaign_df.empty: #get campaign analytics data campaign_ids = ln_campaign_df["campaign_id"] campaign_analytics = get_campaign_analytics(access_token,campaign_ids,s_date,e_date) print("\n campaigns analytics :\n",campaign_analytics) else: campaign_analytics = pd.DataFrame() print("\n campaigns analytics :\n",campaign_analytics) print("\n Process End \n") except: print("\n Process Failed !! ", sys.exc_info())
3. Create a get_linkedin_data.py python file to retrieve LinkedIn Campaign data
This file handles the core task of extracting reporting and analytics data from LinkedIn Campaigns using the LinkedIn Advertising API. I’ll name it get_linkedin_data.py. Currently, the code retrieves only campaign-level data, but you can expand it to include campaign groups, ads, and creative data as well.
In the sample code below, I’m fetching a few key metrics from a LinkedIn campaign. You can easily modify it to include additional fields from the LinkedIn Metrics list for more comprehensive data.
#!/usr/bin/python3 import requests import pandas as pd import sys import json from datetime import datetime, timedelta import datetime import re from urllib import parse #Function for date validation def date_validation(date_text): try: while date_text != datetime.datetime.strptime(date_text, '%Y-%m-%d').strftime('%Y-%m-%d'): date_text = input('Please Enter the date in YYYY-MM-DD format\t') else: return datetime.datetime.strptime(date_text,'%Y-%m-%d') except: raise Exception('linkedin_campaign_processing : year does not match format yyyy-mm-dd') def get_campaigns_list(access_token,account): try: url = "https://api.linkedin.com/v2/adCampaignsV2?q=search&search.account.values[0]=urn:li:sponsoredAccount:"+account headers = {"Authorization": "Bearer "+access_token} #make the http call r = requests.get(url = url, headers = headers) #defining the dataframe campaign_data_df = pd.DataFrame(columns=["campaign_name","campaign_id","campaign_account", "daily_budget","unit_cost","campaign_status","campaign_type"]) if r.status_code != 200: print("\n !! function (get_linkedIn_campaigns_list) something went wrong !! ",r) else: response_dict = json.loads(r.text) if "elements" in response_dict: campaigns = response_dict["elements"] print("\n Total number of campain in account : ",len(campaigns)) #loop over each campaigns in the account campaign_list = [] for campaign in campaigns: campaign_name = None campaign_id = None campaign_acct = None campaign_obj = None daily_budget = None unit_cost = None tmp_dict = {} #for each campign check the status; ignor DRAFT campaign if "status" in campaign and campaign["status"]!="DRAFT": if "name" in campaign: campaign_name = campaign["name"] tmp_dict["campaign_name"] = campaign_name if "id" in campaign: campaign_id = campaign["id"] tmp_dict["campaign_id"] = campaign_id if "account" in campaign: campaign_acct = campaign["account"] campaign_acct = re.findall(r'\d+',campaign_acct)[0] tmp_dict["campaign_account"] = campaign_acct if "dailyBudget" in campaign: daily_budget = campaign["dailyBudget"]["amount"] tmp_dict["daily_budget"] = daily_budget if "unitCost" in campaign: unit_cost = campaign["unitCost"]["amount"] tmp_dict["unit_cost"] = unit_cost campaign_status = campaign["status"] tmp_dict["campaign_status"] = campaign_status campaign_list.append(tmp_dict) else: print("\n key *elements* missing in JSON data from LinkedIn") campaign_data_df = pd.DataFrame.from_records(campaign_list) try: campaign_data_df["daily_budget"] = pd.to_numeric(campaign_data_df["daily_budget"]) campaign_data_df["unit_cost"] = pd.to_numeric(campaign_data_df["unit_cost"]) except: pass return campaign_data_df except: print("\n !! function get_campaigns_list failed !!",sys.exc_info()) def get_campaign_analytics(access_token,campaigns_ids,s_date,e_date): try: #calling date validation funtion for start_date format check startDate = date_validation(s_date) dt = startDate+timedelta(1) week_number = dt.isocalendar()[1] #calling date validation funtion for end_date format check endDate = date_validation(e_date) #defining the dataframe campaign_analytics_data = pd.DataFrame(columns=["campaign_id","start_date","end_date", "cost_in_usd","impressions","clicks"]) fields = "costInUsd, impressions, clicks" campaign_list = [] for cmp_id in campaigns_ids: #Building api query in form of url dateRange_start = "dateRange.start.day="+str(startDate.day)+"&dateRange.start.month="+str(startDate.month)+"&dateRange.start.year="+str(startDate.year) dateRange_end = "dateRange.end.day="+str(endDate.day)+"&dateRange.end.month="+str(endDate.month)+"&dateRange.end.year="+str(endDate.year) url = f"https://api.linkedin.com/v2/adAnalyticsV2?q=analytics&pivot=CAMPAIGN&{dateRange_start}&{dateRange_end}&timeGranularity=ALL&campaigns[0]=urn:li:sponsoredCampaign:{str(cmp_id)}&fields={fields}" #defining header for authentication headers = {"Authorization": "Bearer "+access_token} #make the http call r = requests.get(url = url, headers = headers) if r.status_code != 200: print("\n !! function (get_LinkedIn_campaign) something went wrong !! ",r) else: response_dict = json.loads(r.text) if "elements" in response_dict: campaigns = response_dict["elements"] for campaign in campaigns: tmp_dict = {} cmp_costInUsd = float(campaign["costInUsd"]) tmp_dict["cost_in_usd"] = round(cmp_costInUsd,2) cmp_impressions = campaign["impressions"] tmp_dict["impressions"] = cmp_impressions cmp_clicks = campaign["clicks"] tmp_dict["clicks"] = cmp_clicks tmp_dict["campaign_id"] = cmp_id tmp_dict["start_date"] = startDate tmp_dict["end_date"] = endDate tmp_dict["week"] = week_number tmp_dict["month"] = startDate.month campaign_list.append(tmp_dict) else: print("\n !! key *elements* missing in JSON data from LinkedIn !!") campaign_analytics_data = pd.DataFrame.from_records(campaign_list) campaign_analytics_data["start_date"] = startDate campaign_analytics_data["end_date"] = endDate return campaign_analytics_data except: print("\n !! function get_campaign_analytics failed !! ",sys.exc_info())
Congratulations! You have successfully developed Python code to extract LinkedIn campaign analytics data using LinkedIn Adversting API. You can also look at Python code to extract LinkedIn Profile data (i.e. LinkedIn Account Details).
Hope I was able to solve the problem. If you like this article and think it was easy to understand do share it with your friends and connection. Thank you! See you soon.
For any suggestions or doubts ~ Get In Touch
Checkout out my other API Integration and Coding Solution Guide