Skip to main content
LinkedIn lead form sync reads responses from the forms you declare and writes each response as a lead in your lead dataset. Erdo checks every 15 minutes. The capability is behind a feature flag that is off by default; staff users have it enabled. The dataset must have lead identity turned on.

Declare a source

Use PUT /v1/provider-lead-sources to replace the declaration for one provider and ad account. dataset is the dataset slug. provider is currently linkedin_ads. connection_id is the connected LinkedIn Ads integration account id. account_id is the numeric LinkedIn ad account id. forms is the list of LinkedIn lead gen form ids. enabled is optional and defaults to true. A form must belong to the named ad account. Erdo refuses the save when it does not, and when another organization has already declared the same form. Use this preview with accounts dedicated to your organization: a form declaration does not establish ownership within an account shared by multiple customers. Responses from any other account or any other form are never written.
Discover form IDs through GET /v1/provider-lead-sources/forms?connection_id=<connector-account-id>&account_id=<ad-account-id>. Read declarations you can view, with optional provider and account filters:
Delete a declaration by provider and account. Both query parameters are required for this operation:
The CLI provides the same operations:
Repeat --form for more forms. The file form accepts one JSON object, and --file - reads it from standard input. Use --disabled with flag input to save the declaration disabled. The forms command’s --connection-id is the connector account id, not the native integration id. Get it from the account_id field of the matching connection in GET /connectors/my-connections (the response may also include integration_id, which is a different id). Use that connector account id with the numeric LinkedIn ad account id to discover available form ids, names, states and version ids.

Backfill and progress

The first sync of a newly declared form backfills its available responses, including older responses still retained by LinkedIn. Adding a form later also backfills that form. Moving a declaration to another dataset does not backfill the forms again; new responses continue into the selected dataset. Responses are fetched in pages. Erdo advances through them progressively and stores progress so an interrupted run can resume instead of starting over. Explicit checkbox answers populate the existing consent columns. A combined yes requires all returned consent checkboxes to be accepted. No consent answers means no consent stamp; a later declined answer never downgrades a recorded yes. If the declared dataset is missing, Erdo disables that source so it cannot keep retrying writes to a dataset that no longer exists. After three consecutive sync failures, Erdo raises an attention item for the organization. The source’s last_error and last_run_at remain available from list to diagnose the failure. A response’s answers are read against the exact lead form version it was submitted against. If you edited a form, LinkedIn may no longer return the earlier version, and those responses cannot be read — Erdo records them and raises one attention item naming them, rather than retrying forever. Later responses on the current version are unaffected and keep arriving; the answers for the recorded ones are still downloadable from LinkedIn Campaign Manager.

Sync timing and deduplication

The first sync looks back 90 days, which is the period for which LinkedIn keeps responses. Later syncs reread the last 48 hours so late responses are caught. A response is written once even when Erdo reads it more than once.

Columns in a lead row

Every lead row gets email, phone, first_name, last_name, and the other LinkedIn profile fields the form asks for. Profile field names are lowercase snake case, such as job_title, company_name and work_email. The location fields are location_city, location_state, location_country and postal_code, because city and country already record where a visitor’s browser was. When a form asks only for a work email or a work phone, that value also fills email or phone so the lead can be reached. Custom questions use a column named from the question name, converted to lowercase with underscores. If that name would collide with a reserved column, Erdo prefixes it with question_. The hidden fields utm_source, utm_medium, utm_campaign, utm_term, utm_content, utm_id, linkedin_campaign_id, linkedin_ad_set_id, linkedin_ad_id, and linkedin_account_id are copied when the form contains a static value. Dynamic {{CAMPAIGN_ID}}, {{CREATIVE_ID}}, and {{ACCOUNT_ID}} values are filled from the response. Other dynamic values are left blank, not written as literal tokens. The campaign, ad, and account ids are always filled from the response itself. The row also contains provider_lead_id, the LinkedIn response id, provider_form, the versioned form URN, and source, which is always linkedin_lead_gen_form. submitted_at is when Erdo wrote the row and is the timestamp that alerts and automations key on. ts is when the person submitted on LinkedIn. is_test is LinkedIn’s test lead flag.

Checking a source

Each declaration in the list response carries synced_through, the submission time every earlier response has been handled through, last_run_at, and last_error, which says why the last sync did not finish (for example a connection that needs reconnecting). A response that could not be written is read again on the next sync. A response whose form asked for neither an email nor a phone identifies nobody and is not written. Deleting a declaration leaves the leads already written in place. Declaring the same account again never writes a response a second time.

Requirements

The LinkedIn Ads connection must have LinkedIn’s Lead Sync permission, r_marketing_leadgen_automation. The member who connects it also needs a qualifying role on the ad account and its company page.