Configure Customer Application and ATS Integration

You can embed a LinkedIn widget in your platform that allows customers to log-in, select the Premium Job Posting contract, and enable the Premium Job Posting within the partner’s platform.
Once enabled, the partner platform will be able to post premium jobs on behalf of the customer. You can integrate the onboarding widget to let LinkedIn's Recruiter customers post paid jobs directly into their contract, without leaving the partner site.

Note

  • A customer who has either the Dashboard Manager Admin or Recruiter Admin seat in LinkedIn Recruiter can opt into the premium job posting from this widget
  • This widget can be either live on your Job Board Settings page (preferable) or LinkedIn Global Settings page (where the RSC customer onboarding widget is also hosted)
  • Refer this link for more information about job promotion at LinkedIn

Steps to Onboard PJP Widget

Follow the below steps to for OnBoarding Widget implementation:

  1. Create and Configure a Customer App
  2. Display the Customer Onboarding Widget Plugin
  3. Update Customer Integrations
  4. Widget Enablement Stages

Step 1 - Create and Configure a Customer App

The Provisioning API allows you to create API keys for each of your customers. Please note that you will need to store a unique API key for each of your customers. Once your app is configured, you may begin making API requests and testing the integration. All API requests require authorization.

Note

For existing CSA customers, you will be using their existing API keys. Please contact your Partner Engineering representative to coordinate migrating these API keys.

Step 2 - Display the Customer Onboarding Widget Plugin

The Onboarding Widget allows the API partners to integrate and let the LinkedIn Recruiter customers post paid jobs directly into their contract, without leaving the partner site.

Widget Script

Once a new customer application is created, it may take up to five minutes for the widget to load. You can host this widget by leveraging the below lines of Javascript code:

<script type="text/javascript" src="https://platform.linkedin.com/xdoor/scripts/in.js">
api_key: {customer app API key goes here}
extensions: UJPWidget@https://platform.linkedin.com/rsc/extensions/ujp-onboarding-widget
</script>

<script type="IN/UJPWidget" data-onconfirmjobposter="confirmJobPoster"
data-width="{width}">
</script>

<script>
/**
* This callback should:
*Store the customer's integration details like contractID in your ATS. These values will be used to promote jobs on LinkedIn on behalf of customer
* @param {Object[]} integrations
* @param {string} integrations[].tenantType
* @param {string} integrations[].onboardingStatus
* @param {string} integrations[].integrationType
* @param {string} integrations[].integrationContext
* 
*/
function confirmJobPoster(integrations) {
//Your code here
console.log("integrations:", integrations);
}
</script>

Note

  • Use the Customer's Application Client ID obtained as a value for api_key in above plugin to display the New Customer Onboarding Widget Plugin
  • In order to reload the widget on a single page application, use in.parse()
  • Verify Content Security Policy includes "platform.linkedin.com" and "www.linkedin.com" and ensure these domains are allowed in your platform
  • Please add the host domain of widget under application settings on https://developer.linkedin.com

Widget Load

The plugin loads based on the api_key and data-width attributes you specify. Use the latter attribute to declare the width of the widget.

Widget Callback

The callback specified for the data-onconfirmjobposter script attribute will be fired when the customer selects the default job poster and clicks the Save button. You need to store the values you retrieve per customer for contractID as it will be used for posting premium job on behalf of this customer.

Widget will return 4 values
{
tenantType: JOBS
onboardingStatus: REQUESTED
integrationType: PREMIUM_JOB_POSTING
integrationContext: urn:li:contract:<contract_id>
}

Customer Enablement Flow

To enable premium job posting, a LinkedIn contract seatholder with admin privileges has to perform a few steps in your platform when the javascript widget is loaded:

Note

These steps are for the customers of the partners.

  1. Click Sign in
    widget screen1

  2. Enter your LinkedIn credential
    widget screen2

  3. If you have a seat on multiple LinkedIn contracts, select one you would like to connect to your ATS
    widget screen3

    Note

    • If you only have a seat on one LinkedIn contract, you will bypass this page
    • The widget also provide an option to the customer to change the contract if they wish to enable premium job posting for more than one contracts. This will be one time enablement step per contract. Once enabled, partner platform can promote all jobs using API on behalf of the customer. There is only one client_id per customer
  4. The admin seat holder of the LinkedIn contract will be prompted to select the default Job Poster to display alongside their jobs. At this point, the customer can select one of the seat holders of their Recruiter Contract.
    widget screen4

  5. In case the contract falls under the recommended budget type, you are given the choice to activate the posting of promoted jobs with a budget recommended by LinkedIn. Please note that this page does not display for contracts based on job slots.
    widget screen5

  6. Once the default job poster is selected, customers are directed to this following landing page after partner approves their integration request with update customer integration call.
    widget screen6

  7. If the contract selected is for the recommended budget on LinkedIn, clients are directed to the subsequent landing page.
    widget screen7

    Note

    The widget allows the customer to update the default job poster value anytime in future. It is necessary for partners to execute the following API request every time there is a modification in the default job poster

Step 3 - Update Customer Integrations

Once the customer clicks the Save button, the widget invokes the callback method configured in partner platform and provides below parameters:

  • tenantType: JOBS
  • onboardingStatus: REQUESTED
  • integrationType: PREMIUM_JOB_POSTING
  • integrationContext: urn:li:contract:<contract-id>

Enable Customer Integrations

POST https://api.linkedin.com/v2/atsIntegrations?ids[0].integrationContext=urn:li:contract:(ContractID returned by widget) &ids[0].integrationType=PREMIUM_JOB_POSTING&ids[0].tenantType=JOBS&ids[0].dataProvider=ATS

Note

Create access token using the customer application client Id used in background for widget to make this API call. Creating integrations must be done server-side and in real-time.

For each id part specified in the request:

  • Use the customer's integration context obtained in step 2 as the value of id[i].integrationContext . The format will be either urn:li:organization:{id} or urn:li:contract:{id}
  • Use the integration type obtained in step 2 as the value of id[i].integrationType
  • Use the tenant type obtained in step 2 as the value of id[i].tenantType
  • Use "ATS" as the value of id[i].dataProvider

The partner should:

  1. Persist contractID detail
  2. Immediately invoke LinkedIn’s ATSIntegrations endpoint to enable customers’ premium job posting integration.
    The API call will be as below:

Provide Customer Integration Name

API URL

POST https://api.linkedin.com/v2/atsIntegrations?ids[0].integrationContext=urn:li:contract:(ContractID returned by widget) &ids[0].integrationType=PREMIUM_JOB_POSTING&ids[0].tenantType=JOBS&ids[0].dataProvider=ATS
Request Headers:
Authorization: Bearer {token}
x-restli-method: batch_partial_update

Sample Request Body

{
  "entities": {
    "integrationContext=urn:li:contract:<ID>&integrationType=PREMIUM_JOB_POSTING&tenantType=JOBS&dataProvider=ATS": {
      "patch": {
        "$set": {
          "integrationName": "<PartnerName>-<CustomerName> LinkedIn Premium Job Posting Integration"
        }
      }
    }
  }
}

Sample Response Body

{
    "errors": {},
    "results": {  "integrationType=PREMIUM_JOB_POSTING&tenantType=JOBS&dataProvider=ATS&integrationContext=urn:li:contract:<ID>": {
            "status": 204
        }
    }
}

The above step will successfully enable premium job posting integration for your customer. You can also pull the status of the integration by making a GET call

Note

Be sure to check the response for error statuses corresponding to individual entities you submit.

Step 4 - Widget Enablement States

The PJP Widget has three distinct states which are determined by the actions of our customers. If the following text displays at the widget, the customers can utilize their paired customer application API key and contract for the specified organization_id to post premium jobs.
widget state

  1. Once the customer logs into the widget for the first time and no default job-poster is selected yet, the widget displays “Not Connected”.
    widget stage1
  2. After you select the default job poster and click the Save button, the widget displays “Premium Job Posting is requested”. Every time a customer changes or removes default job poster from their contract via this widget, integration reverts to “Requested” state. Partner ATS must run an Update Customer Integration API call to re-enable customers for job posting.
    widget stage2
  3. After the default job poster is associated with this integration, the widget state will be displayed as “Premium Job Posting is enabled”. Depending on whether the customer has chosen a contract that falls under the recommended budget type or not, they will be presented with one of two widget states.
    widget stage3
    widget stage3a

Widget Errors

Customers can see following errors while configuring with widget:

Error Message Description Resolution
You don't have permission to view this page. Log in as a Recruiter Admin to view this page When the widget is loaded with API key which does not have correct permission to access the widget Log in as a Recruiter Admin to view this page
Something went wrong. There was an issue with our servers. Please try again When widget is unable to fetch permission for the API key provided Try reloading the widget
Something went wrong. There was an issue with our servers. Please try again When widget is unable to fetch integration configuration for the API key provided Try reloading the widget
Something went wrong. There was an issue with our servers. Please try again If the fetching of the profile of the job-poster fails for an already saved job-poster Try reloading the widget
An error occurred when fetching data. Please try again While searching for a particular job poster, fetching of profiles fail on entering search key into input field Retry with the key again, by deleting and reentering the key
Saving the default poster failed due to a network error. Please try again or contact LinkedIn Support If the saving of default job poster fails Try again, as this is a server error
Please select a job poster from the drop down If the user clicks the Save button without selecting a valid job poster Always try to choose user from suggeted drop down
No data found If the user enters a default job poster and relevant results as suggestions are not present within LinkedIn users Please recheck if the entered job poster is spelled correctly to match the details of the profile
Saving the recommended budget setting failed due to a network error. Please try again or contact LinkedIn Support If the saving of recommended budget setting fails Try again, as this is a server error
Something went wrong. There was an issue with our servers. Please try again Fetching the recommended budget setting fails while loading the widget Try reloading the widget