Product Builder Resources šŸ¤“

Introduction

New to navigating the SafeGraph schema? Need to calculate deltas, find particular sets of POIs, or understand how to interpret relationships in our data? You're not alone, and this page is for you!

See below for common questions and workflows - along with example queries - to help kickstart your journey from "I have SafeGraph data" šŸ¤·ā€ā™‚ļø to "I am realizing valuable insights from SafeGraph data!" šŸ’”

  • Query Example Notes:
    • All code examples are in SQL. If a different language is preferred, paste the code sample into AI (OpenAI, Google Gemini, etc.) and prompt the AI to "Convert this code from SQL to [desired language]."
    • The table names (following FROM statements) are generic and will need to reflect whatever table name you assign to our data in your environment. In the examples below, the generic table names store the following attributes:
    • Queries involving more than 1 release will designate places_old and places_new table names and/or [column name]_oldand [column_name]_new column names.

Places

Detecting change across releases

  • Prompt: "I need to know which places were removed, added, or saw a specific column value change compared to the previous release."

Change Type

Query

View all places added

SELECT places_new.* FROM places_old RIGHT JOIN places_new ON places_old.placekey = places_new.placekey WHERE places_old.placekey IS NULL

View all places removed

SELECT places_new.* FROM places_old RIGHT JOIN places_new ON places_old.placekey = places_new.placekey WHERE places_old.placekey IS NULL

View all places with a specific column value change

Places with an open_hours change ex:


SELECT places_new.placekey, places_old.open_hours as open_hours_old, places_new.open_hours as open_hours_new FROM places_old INNER JOIN places_new ON places_old.placekey = places_new.placekey WHERE places_old.open_hours <> places_new.open_hours

Places that closed (closed_on change) ex:

SELECT places_new.placekey, places_old.closed_on as closed_on_old, places_new.closed_on as closed_on_new FROM places_old INNER JOIN places_new ON places_old.placekey = places_new.placekey WHERE places_old.closed_on IS NULL AND places_new.closed_on IS NOT NULL


Isolating Premium Rows

For customers that subscribe to our "premium" rows like industrial, apartments, and point POIs (see docs to learn more).

  • Prompt: "I license premium row POIs and want to find them."

Premium Row Type

Query

Point POIs

SELECT * FROM places WHERE geometry_type = 'POINT'

EV charging stations only ex:

SELECT * FROM places WHERE geometry_type = 'POINT' AND naics_code = 447190

Apartments

SELECT * FROM places WHERE naics_code = 531110

Industrial POIs: Warehousing and Storage, Mini Warehouses and Self-Storage Units, Couriers and Express Delivery Services, Data Centers, Refrigerated Warehousing and Storage, Industrial Equipment Wholesalers,
Other Merchant Wholesalers, Manufacturing Facilities, Motor Vehicle Manufacturing, Aircraft Manufacturing

SELECT * FROM places WHERE naics_code LIKE '4931%' OR naics_code = 531130 OR naics_code = 492110 OR naics_code = 518210 OR naics_code = 493120 OR naics_code LIKE '4238%' OR naics_code = 424490 OR naics_code = 423910 OR naics_code LIKE '3399%' OR naics_code LIKE '3361%' OR naics_code = 336411


How to find important/prominent POIs

We know that some places are more important than others and have specifically built our data to reflect customer requirements for a growing list of POI definitions across many countries. The following list of place definitions have had concerted efforts to ensure that we:

1.) Provide full coverage in the specified geography

2.) Enable customers to isolate only these POIs from a single query that guards against "noise" and/or other POIs with a "close-but-not-exact" definition match. NAICs are often not 1:1 matches for specific POI definitions, so some queries further narrow within a single naics_code or stretch across more than one naics_code using other features.

POI Scope

Geography

Query

Geometry

Sports Venues (except car and horse racing tracks). List of applicable category_tags designating the main sport(s) played at the venue plus any known professional, collegiate, or sanctioned club teams affiliated with the venue as available.

US, CA, Western Europe, AU

NBA Arenas ex:


SELECT * FROM places WHERE naics_code = 711211 AND category_tags LIKE '%National Basketball Association%'

Captures the entire premise of the venue. Sub-venue POIs should reflect the venue in parent_placekey.

Car and Horse Racing Venues.
List of applicable category_tags designating the main sport (Racing or Horse Racing) raced at the track plus major car racing leagues affiliated with the venue as available.

US, CA, Western Europe, AU

NASCAR Stadiums ex:


SELECT * FROM places WHERE naics_code = 711212 AND category_tags LIKE '%NASCAR%'

Captures the entire premise of the venue. Sub-venue POIs should reflect the venue in parent_placekey.

Performance Art Venues. List of applicable category_tags designating a more granular description of the venue type (ex: "Convention Center", "Music Arena", etc.) as available.

US, CA, Western Europe, AU

Music Arenas ex:


SELECT * FROM places WHERE naics_code = 711310 AND category_tags LIKE '%Music Arena%'

Captures the entire premise of the venue. Sub-venue POIs should reflect the venue in parent_placekey.

International and Large Regional Airports

GLOBAL

SELECT * FROM places WHERE naics_code = 488119

Captures the entire premise of the airport. Sub-airport POIs should reflect the airport in parent_placekey.

Terminals and Concourses within International and Large Regional Airports. "International Terminal" and "Domestic Terminal" are possible category_tag values.

US

SELECT * FROM places WHERE naics_code = 488119 AND LENGTH(category_tags) > 2

Captures the entire terminal/concourse premise. Sub-terminal/concourse POIs should reflect the terminal/concourse in parent_placekey, and the terminal/concourse itself should reflect the larger airport in parent_placekey.

Prisons and Jails. Includes small, municipal jails and detention centers as well as maximum security federal prisons.

US

SELECT * FROM places WHERE naics_code = 922140

Captures the entire prison/jail premise. In many cases, we do not have sub-prison/jail POIs, but where we do, they should reflect the prison/jail in parent_placekey.

Shopping Malls. Note that place_format shows the mall type per ICSC classifications (see docs for definitions on 11 possible values).

US and CA

SELECT * FROM places WHERE naics_code = 531120

Captures the entire premise of the mall. Mall tenant POIs should reflect the mall in parent_placekey.

College/University Campuses for 4-year universities, junior colleges, trade schools, etc. These are depicted by the following naics_codes: 611210 (Junior Colleges), 611310 (Colleges, Universities, and Professional Schools), 611511 (Cosmetology and Barber Schools), 611512 (Flight Training), 611519 (Other Technical and Trade Schools), 611610 (Fine Arts Schools), 611630 (Language Schools), 611692 (Automobile Driving Schools), 611699 (All Other Miscellaneous Schools and Instruction). Note that place_format = "Higher Education" (see docs) depicts the main campus and is required to exclude similarly named and categorized sub-campus POIs like "the business school."

US and CA

Junior Colleges ex:


SELECT * FROM places WHERE naics_code = 611210 AND place_format LIKE '%Higher Education%'

Captures the entire premise of the college campus. Sub-campus POIs should reflect the main campus in parent_placekey.

Primary and Secondary Schools: Kindergarten through high school for public and private/charter/boarding schools. The following category_tag values help indicate when the school primarily hosts pupils aged 13 and below (relevant for adhering to COPPA advertising regulation): "Boarding School", "Early Childhood Education", "Elementary School", "High School", "Home School", "K–12 School", "Middle School", "Montessori School", "Private School", "Public School", "Religious School", "Secondary School", "Special Education School", "Waldorf School", "Youth Programs & Services".

US and CA

SELECT * FROM places WHERE naics_code = 611110

Geometry exists, but precise polygons are not available for all locations. We expect to close this gap by the July 2025 release.

Places Of Worship for all recognized religious groups.

US and CA

SELECT * FROM places WHERE naics_code = 813110 AND category_tags LIKE '%Place of Worship%'

Captures the entire premise of the place of worship. Sub-place of worship POIs should reflect the place of worship in parent_placekey.

US Military Bases. The following category_tags depict which branch of military operates from each base: "US Army", "US National Guard", "US Air Force", "US Navy", "US Marine Corps", "US Defense Logistics Agency", or "US Space Force".

GLOBAL

US Air Force ex:


SELECT * FROM places WHERE naics_code = 928110 AND category_tags LIKE '%US Air Force%'

Captures the entire premise of the military base. Sub-military base POIs should reflect the military base in parent_placekey.

US Federal, State, and Local Courthouses. Federal courthouses have "Courthouses" category_tags while state and local courthouses have null category_tags.

US

Federal Courthouses ex:


SELECT * FROM places WHERE naics_code = 922110 AND category_tags LIKE '%Courthouses%'

Captures the entire premise of the courthouse.

Hospital Campuses. Does not include sub-hospital campus POIs like "Trauma Center" or "Cardiology").

SE, NO, DK, FI

SELECT * FROM places WHERE naics_code = 622110

Precise geometry not currently supported for most locations.

Shopping Malls

SE, NO, DK, FI

SELECT * FROM places WHERE naics_code = 531120

Precise geometry not currently supported for most locations.

College/University Campuses. Includes standard, 4-year universities and trade/technical colleges.

NO, DK, PL

4-year Universities ex:


SELECT * FROM places WHERE naics_code = 611310

Trade/technical Colleges ex:


SELECT * FROM places WHERE naics_code = 6113

Precise geometry not currently supported for most locations.

College/University Campuses. Includes satellite campuses affiliated with a given university - designated by the word "campus" in location_name.

SE

SELECT * FROM places WHERE naics_code = 611310

Satellite Campuses excluded ex:


SELECT * FROM places WHERE naics_code = 611310 AND lOWER(location_name) NOT LIKE '%campus%'

Precise geometry not currently supported for most locations.

College/University Campuses

FI

SELECT * FROM places WHERE naics_code = 611310

Precise geometry not currently supported for most locations.

Primary and Secondary Schools: Kindergarten through high school for public and private/charter/boarding schools. Kindergarten-only schools have "Elementary School" category_tags.

PL

SELECT * FROM places WHERE naics_code = 611110

Precise geometry not currently supported for most locations.

Nationally Protected Parks, Monuments, Preserves, etc. as defined by the National Park Service. The following category_tags depict the type of protected place: "National Park", "National Monument", "National Preserve", "National Recreation Area", "National Historical Park", "National Historic Site", "National Memorial".

US

National Parks ex:


SELECT * FROM places WHERE naics_code = 712190 AND category_tags LIKE '%National Park%'

Captures the entire premise of the national park/preserve/etc. Sub-park POIs should reflect the park in parent_placekey.


Isolating POIs by unique features

For customers who leverage rich attributes like category_tags (docs) and/or amenity columns (docs) to isolate POI subsets meeting specific criteria. Commonly used by mapping and generative AI platforms to support user search, marketers to create location based audiences or plan OOH (out of home) campaigns, retailers to support real estate site selection, etc.

Prompt

Query

"I want to find sports bars in New York that have a TV, wifi, parking, happy hour, burgers, and accept reservations."

SELECT * FROM places WHERE region = 'NY' AND category_tags LIKE '%Sports Bar%' AND category_tags LIKE '%Burgers%' AND amenities LIKE '%TV%' AND accessibility LIKE '%Parking%' AND service_options LIKE '%Accepts Reservations%' AND service_options LIKE '%Happy Hour%'

"I want to identify cafes in California that offer bagels, delivery, have outdoor seating, and are family friendly with a casual vibe."

SELECT * FROM places WHERE region = 'CA' AND category_tags LIKE '%Cafe%' AND category_tags LIKE '%Bagels%' AND amenities LIKE '%Outdoor Seating%' AND service_options LIKE '%Delivery%' AND setting LIKE '%Family Friendly%' AND setting LIKE '%Casual%'

"I want to find Department Stores in Texas that sell perfume."

SELECT * FROM places WHERE region = 'TX' AND category_tags LIKE '%Department Store%' AND category_tags LIKE '%Perfume%'


How to link brand relationships

See brands and brand_info docs to learn about how we qualify "brands" and what details we capture.

Prompt

Query

"I want to understand which brand locations in places are owned by a parent brand/company."

WITH parent_brands AS ( SELECT A.brand_name as child_brand, A.safegraph_brand_id as child_brand_id, A.stock_symbol as child_stock_symbol, A.stock_exchange as child_stock_exchange, B.brand_name as parent_brand, B.safegraph_brand_id as parent_brand_id, B.stock_symbol as parent_stock_symbol, B.stock_exchange as parent_stock_exchange FROM brand_info A LEFT JOIN brand_info B ON A.parent_safegraph_brand_id = B.safegraph_brand_id )

SELECT parent_brands.*, places.* FROM places LEFT JOIN parent_brands ON ARRAY_CONTAINS(places.safegraph_brand_ids, parent_brands.child_brand_id) WHERE parent_brand is not null

"I want to understand which brand locations in places are owned by a parent brand/company that is also owned by a parent brand/company."

WITH parent_brands AS ( SELECT A.brand_name as child_brand, A.safegraph_brand_id as child_brand_id, A.stock_symbol as child_stock_symbol, A.stock_exchange as child_stock_exchange, B.brand_name as parent_brand, B.safegraph_brand_id as parent_brand_id, B.stock_symbol as parent_stock_symbol, B.stock_exchange as parent_stock_exchange, B.parent_safegraph_brand_id as grand_parent_brand_id FROM brand_info A LEFT JOIN brand_info B ON A.parent_safegraph_brand_id = B.safegraph_brand_id ),

grand_parent_brands AS ( SELECT child_brand, child_brand_id, child_stock_symbol, child_stock_exchange, parent_brand, parent_brand_id, parent_stock_symbol, parent_stock_exchange, brand_info.brand_name as grand_parent_brand, grand_parent_brand_id, brand_info.stock_symbol as grand_parent_stock_symbol, brand_info.stock_exchange as grand_parent_stock_exchange FROM parent_brands LEFT JOIN brand_info ON parent_brands.grand_parent_brand_id = brand_info.safegraph_brand_id )

SELECT grand_parent_brands.*, places.* FROM places LEFT JOIN grand_parent_brands ON ARRAY_CONTAINS(places.safegraph_brand_ids, grand_parent_brands.child_brand_id) WHERE grand_parent_brand IS NOT NULL


Geometry

How to navigate parent<>child spatial relationships

Prompt

Query

"I want to see places and geometry columns for a POI's parent (and the parent's parent when applicable)."

WITH parents AS ( SELECT A.placekey as child_placekey, A.parent_placekey as child_parent_placekey, A.location_name as child_location_name, A.street_address as child_street_address, A.city as child_city, A.region as child_region, A.postal_code as child_postal_code, A.iso_country_code as child_iso_country_code, A.latitude as child_latitude, A.longitude as child_longitude, A.naics_code as child_naics_code, A.top_category as child_top_category, A.sub_category as child_sub_category, A.polygon_wkt as child_polygon_wkt, A.wkt_area_sq_meters as child_wkt_area_sq_meters, A.polygon_class as child_polygon_class, A.enclosed as child_enclosed, B.placekey as parent_placekey, B.parent_placekey as grand_parent_placekey, B.location_name as parent_location_name, B.street_address as parent_street_address, B.city as parent_city, B.region as parent_region, B.postal_code as parent_postal_code, B.iso_country_code as parent_iso_country_code, B.latitude as parent_latitude, B.longitude as parent_longitude, B.naics_code as parent_naics_code, B.top_category as parent_top_category, B.sub_category as parent_sub_category, B.polygon_wkt as parent_polygon_wkt, B.wkt_area_sq_meters as parent_wkt_area_sq_meters, B.polygon_class as parent_polygon_class, B.enclosed as parent_enclosed FROM places A LEFT JOIN places B ON A.parent_placekey = B.placekey )

SELECT parents.*, places.placekey as grand_parent_placekey, places.parent_placekey as great_grand_parent_placekey, places.location_name as grand_parent_location_name, places.street_address as grand_parent_street_address, places.city as grand_parent_city, places.region as grand_parent_region, places.postal_code as grand_parent_postal_code, places.iso_country_code as grand_parent_iso_country_code, places.latitude as grand_parent_latitude, places.longitude as grand_parent_longitude, places.naics_code as grand_parent_naics_code, places.top_category as grand_parent_top_category, places.sub_category as grand_parent_sub_category, places.polygon_wkt as grand_parent_polygon_wkt, places.wkt_area_sq_meters as grand_parent_wkt_area_sq_meters, places.polygon_class as grand_parent_polygon_class, places.enclosed as grand_parent_enclosed FROM parents LEFT JOIN places ON parents.grand_parent_placekey = places.placekey