Nextdoor
N
Nextdoor

tap-nextdoor (meltanolabs variant)

Nextdoor is a neighbourhood social network. Nextdoor Ads Manager (NAM) is its self-serve advertising platform, where businesses run campaigns targeted at specific neighbourhoods, postal codes or radii, and measure them with the Nextdoor conversion pixel.

This tap extracts the objects an advertiser manages in NAM - advertisers, campaigns, ad groups, ads, creatives and custom audiences - plus performance reporting, through the Nextdoor Ads API.

Some NAM actions remain UI-only (initial sign-up, payment methods, adding or archiving custom audiences, archiving media assets), so they cannot be extracted.

Available Streams

| Stream | Replication | Replication Key | |---|---|---| | users | Full Table | — | | profiles | Full Table | — | | advertisers | Full Table | — | | campaigns | Incremental | updated_at | | ad_groups | Incremental | updated_at | | ads | Incremental | updated_at | | creatives | Incremental | updated_at | | reports | Full Table | — | | ad_stats | Full Table | — | | performance_report | Full Table | — | | custom_audiences | Incremental | updated_at |

users

The NAM user that owns the access token, and which advertisers they can reach.

| Field | Type | Description | |---|---|---| | id | string | The user's ads ID | | name | string | User's display name | | email | string | User's email address | | email_confirmed | boolean | Whether the user has confirmed their email | | advertisers_with_access | array | Advertisers this user can access, with their role on each |

profiles

The advertising profile behind the token, including its billing profile and whether it is an agency.

| Field | Type | Description | |---|---|---| | id | string | The profile's ads ID | | name | string | Profile name | | associated_user_ids | array | Users attached to this profile | | payment_profile_id | string | Billing profile backing this advertising profile | | is_ad_agency | boolean | Whether the profile represents an agency |

advertisers

Advertiser accounts the token can access. Read from the /me endpoint, since the Ads API has no advertiser list endpoint, and optionally narrowed with Advertiser IDs.

| Field | Type | Description | |---|---|---| | advertiser_id | string | Advertiser ID. Sourced from id in the API response, which the reference docs call advertiser_id. | | role | string | The token holder's role on this advertiser, e.g. CLIENT_ADMIN |

campaigns

Campaigns, with objective, status and flight dates.

Supports incremental replication using updated_at.

| Field | Type | Description | |---|---|---| | id | string | Campaign ID | | advertiser_id | string | ID of the advertiser that owns the campaign | | name | string | Campaign name | | status | string | Effective delivery status, e.g. ACTIVE, PAUSED, ARCHIVED. May differ from user_status when a parent is paused. | | user_status | string | Status explicitly set by the advertiser | | objective | string | Campaign objective, e.g. CONVERSION, TRAFFIC | | sub_objective | string | Objective refinement, e.g. WEBSITE_CONVERSIONS. Undocumented. | | special_ad_category | boolean | Whether the campaign is in a regulated category (housing, credit, employment). Undocumented. | | created_at | datetime | When the campaign was created | | updated_at | datetime | When the campaign was last modified — replication key | | start_time | datetime | Scheduled start of delivery | | end_time | datetime | Scheduled end of delivery; absent if open-ended |

ad_groups

Ad groups, carrying the bid, budget, placements, frequency caps and all targeting.

Supports incremental replication using updated_at.

| Field | Type | Description | |---|---|---| | id | string | Ad group ID | | advertiser_id | string | Owning advertiser ID | | campaign_id | string | Parent campaign ID | | name | string | Ad group name | | status | string | Effective delivery status, e.g. ACTIVE, PAUSED_DUE_TO_CAMPAIGN_PAUSE | | user_status | string | Status explicitly set by the advertiser | | placements | array | Where ads may serve, e.g. FEED, FSF, RHR | | audience_network_is_on | boolean | Whether off-Nextdoor audience network delivery is enabled | | bid | object | Bid settings for the ad group | | budget | object | Budget settings for the ad group | | start_time | datetime | Scheduled start of delivery | | end_time | datetime | Scheduled end of delivery; absent if open-ended | | frequency_caps | array | Limits on how often one neighbour sees these ads | | targeting | object | Geographic, audience, interest and daypart targeting | | custom_audience_ids | array | Custom audience IDs. Documented as a top-level field but not returned by the live API, which nests them under targeting.custom_audience_targeting; both are read. | | created_at | datetime | When it was created | | updated_at | datetime | When it was last modified — replication key |

ads

Individual ads, linking an ad group to the creative it renders.

Supports incremental replication using updated_at.

| Field | Type | Description | |---|---|---| | id | string | Ad ID | | advertiser_id | string | Owning advertiser ID | | adgroup_id | string | Parent ad group ID | | creative_id | string | Creative rendered by this ad; joins to the creatives stream | | name | string | Ad name | | status | string | Effective delivery status, e.g. ACTIVE, INACTIVE, ARCHIVED, INELIGIBLE | | user_status | string | Status explicitly set by the advertiser | | created_at | datetime | When the ad was created | | updated_at | datetime | When the ad was last modified — replication key |

creatives

Creative assets - headline, body, call to action, image and logo URLs, and click and impression trackers.

Supports incremental replication using updated_at.

| Field | Type | Description | |---|---|---| | id | string | Creative ID | | advertiser_id | string | Owning advertiser ID | | name | string | Creative name | | status | string | Review status, e.g. APPROVED | | placement | string | Placement this creative targets | | creative_type | string | Creative format, e.g. IMAGE_NATIVE_V3. Undocumented. | | text_overlays | array | Text rendered over the image. Undocumented. | | advertiser_name | string | Advertiser name shown to neighbours | | headline | string | Headline text | | body_text | string | Body copy | | offer_text | string | Offer text, if any | | price | string | Displayed price, if any | | cta | string | Call to action, e.g. Learn more | | canvas_image_url | string | Main creative image | | logo_image_url | string | Advertiser logo | | clickthrough_url | string | Destination URL | | impression_tracking_urls | array | Third-party impression pixels | | click_tracking_urls | array | Third-party click trackers | | created_at | datetime | When it was created | | updated_at | datetime | When it was last modified — replication key |

reports

Saved and scheduled report definitions with their CSV download URLs. Definitions only - this stream carries no metrics.

| Field | Type | Description | |---|---|---| | id | string | Report ID | | advertiser_id | string | Owning advertiser ID | | name | string | Report name | | download_url | string | Presigned S3 URL for the report CSV. Short-lived, and carries embedded AWS credentials - treat as a secret. |

ad_stats

Aggregate performance per ad over the configured window. One row per ad, not a daily time series, and one request per ad, which makes this the slowest stream.

| Field | Type | Description | |---|---|---| | ad_id | string | Ad these metrics are for | | advertiser_id | string | Owning advertiser ID | | start_time | datetime | Start of the reporting window | | end_time | datetime | End of the reporting window, inclusive | | billable_spend | string | Billable spend, currency-prefixed, e.g. "GBP 12.50" | | cpc | string | Cost per click, currency-prefixed | | cpm | string | Cost per thousand impressions, currency-prefixed | | cost_per_result | string | Cost per result, currency-prefixed | | impressions | integer | Impressions served | | clicks | integer | Clicks received | | ctr | number | Click-through rate as a percentage value, e.g. 0.557 means 0.557%. Verified against clicks/impressions on live data. | | result | number | Results against the campaign objective | | total_conversions | integer | All conversions, summing the breakdown below | | purchase_conversions | integer | Purchase conversions | | lead_conversions | integer | Lead conversions | | sign_up_conversions | integer | Sign-up conversions | | add_to_cart_conversions | integer | Add-to-cart conversions | | initiate_checkout_conversions | integer | Checkout-initiated conversions | | search_conversions | integer | Search conversions | | view_content_conversions | integer | View-content conversions | | add_to_wishlist_conversions | integer | Add-to-wishlist conversions | | subscribe_conversions | integer | Subscribe conversions | | other_conversions | integer | Conversions not in the categories above |

performance_report

A custom performance report, defined entirely by the Ad Performance Report setting and built via the reporting API. Its fields are therefore not fixed: the schema is generated from your config, with one column per requested dimension, one per requested metric, plus advertiser_id, report_id and date. See Setup step 4 below for the available metrics and dimensions, and for the caveats - this is the one stream that writes to your account.

Leave the setting unset to skip this stream and use ad_stats instead.

custom_audiences

Custom audiences referenced by ad groups. There is no list endpoint, so audiences are fetched by the IDs found on their ad groups.

Supports incremental replication using updated_at.

| Field | Type | Description | |---|---|---| | id | string | Custom audience ID | | advertiser_id | string | Owning advertiser ID | | adgroup_id | string | The ad group this audience was discovered from | | name | string | Audience name | | description | string | Advertiser's own notes | | audience_type | string | How the audience was built, e.g. emails | | created_at | datetime | When it was created | | updated_at | datetime | When it was last modified — replication key |

Setup

1. Generate an access token

Sign in to Nextdoor Ads Manager and generate an Ads API access token. Set it as Access Token - it is sent as a bearer token on every request.

2. Choose which advertisers to extract (optional)

Leave Advertiser IDs empty to extract every advertiser the token can reach. Set it to narrow extraction to specific advertiser accounts, along with their child campaigns, ad groups and ads.

3. Set the reporting window

Start Date and End Date bound the ad_stats and performance_report streams only. Both accept an ISO-8601 date (2026-01-01) or date-time (2026-01-01T00:00:00Z), and both default to today. End Date is inclusive.

Every other stream replicates on its own updated_at bookmark or in full, and ignores these two settings.

4. Define a performance report (optional)

The performance_report stream builds an ad hoc report from the Ad Performance Report setting:

report:
  metrics: [IMPRESSIONS, CLICKS, CTR, SPEND, BILLABLE_SPEND, CPM, CPC, CONVERSIONS]
  dimension_granularity: [AD]           # CAMPAIGN, AD_GROUP, AD, PLACEMENT
  time_granularity: [DAY]               # DAY, WEEK, MONTH
  name: tap-nextdoor performance report # report name in NAM
  stream_name: performance_report       # rename the stream if you like
  recipient_emails: []                  # every sync emails these
  campaign_ids: []                      # optional filters
  adgroup_ids: []
  ad_ids: []

Every key except the three granularity/metric lists is optional. The same definition as JSON, for the Ad Performance Report setting field or the TAP_NEXTDOOR_REPORT environment variable:

{
  "metrics": ["IMPRESSIONS", "CLICKS", "CTR", "SPEND", "BILLABLE_SPEND", "CPM", "CPC", "CONVERSIONS"],
  "dimension_granularity": ["AD"],
  "time_granularity": ["DAY"],
  "name": "ad performance report",
  "recipient_emails": []
}

All three enum lists are validated before any request is made, so a typo fails with the supported values listed rather than a bare API error.

Caveats - unlike every other stream, this one writes. Each sync creates a report object in the advertiser's account, and those accumulate; the reports stream lists every one created so far. Each sync also emails everyone in recipient_emails - leave it empty to skip the email. Report rows carry no IDs, only Campaign Name, Ad Group Name and Ad Name, so they join to the campaigns, ad_groups and ads streams by name only; renaming an entity in NAM breaks that join.

Leave the setting unset to skip the stream and use ad_stats instead, which is side-effect free but returns a single aggregate row per ad rather than a daily time series, at a cost of one request per ad.

5. Tune pagination (optional)

Page Size sets how many records are requested per page from the list endpoints. It defaults to 100.

Data notes

Money is always returned currency-prefixed ("GBP 3.35") on bids, budgets and all stats spend fields, so those fields are typed as strings rather than parsed, and no currency information is lost.

CTR is expressed as a percentage value in both performance streams - 1.05 means 1.05%.

Campaign and ad group timestamps arrive with a bracketed zone ID (2025-08-26T00:01:34+01:00[Europe/London]), which is invalid against the JSON Schema date-time format. The tap strips the zone ID and keeps the UTC offset, so the instant is unchanged.

Settings

Access Token

Ads API access token, generated in Nextdoor Ads Manager. Sent as a bearer token on every request.

Advertiser IDs

Advertisers to extract data for, by ID, along with their child campaigns, ad groups and ads. Leave empty to extract every advertiser the access token can reach.

Start Date

Start of the reporting window for the performance_report and ad_stats streams. Accepts an ISO-8601 date-time (2026-01-01T00:00:00Z) or a plain date (2026-01-01); the API takes whole days, so any time component is truncated. Defaults to today.

End Date

End of the reporting window, inclusive. Accepts an ISO-8601 date-time (2026-01-31T23:59:59Z) or a plain date (2026-01-31). Defaults to today.

Ad Performance Report

Definition of the custom report built by the performance_report stream. Keys: metrics, dimension_granularity, time_granularity, name, stream_name, recipient_emails, campaign_ids, adgroup_ids, ad_ids. Set stream_name to match the chosen granularity, e.g. campaign_performance_report. NOTE: each sync creates a report in the advertiser's account and emails it to recipient_emails.

Meltano Cloud Connector

Nextdoor connector is available on Meltano. It is built, maintained, supported, and tested by Meltano.

Why Meltano?
Expert supportDirect access to the team that built and maintains Meltano Cloud. Same-day responses during UK business hours. When something breaks, we fix it fast because we know exactly how it works.
Rigorously testedEvery connector goes through comprehensive testing and quality checks before production. Daily monitoring catches issues before they hit your pipelines. We don't just wrap open-source taps and hope for the best. We validate, we test, we maintain.
No maintenance overheadAPI changes. Connector updates. Schema drift. Breaking changes from upstream sources. We handle it all. Your team focuses on using data. Our team focuses on making sure it's there when you need it.
Access to Meltano Slack communityJoin 5,500+ data engineers and analytics practitioners. The community is active, helpful, and always on. Good for quick questions, sharing patterns, and learning what others are building.