GEO 专属投放优化

核心逻辑

传统广告投放面临的最大问题是流量泛化——预算撒向全国,高价值区域得不到足够曝光,低价值区域浪费预算。GEO 投放优化通过地理数据分层,把预算、人群、产品精确匹配到高价值区域,直接提升广告精准度与转化效率。

地理数据采集 → 空间分析 → 区域潜力评分 → 预算/人群/产品分层 → 定向投放 → 数据复盘

一、地理数据采集与清洗

数据来源

数据类型 来源 用途
人口数据 统计局、百度人口数据 区域市场规模评估
经济数据 GDP、人均收入、消费指数 购买力评估
行业数据 搜索量分布、竞品密度 市场需求与竞争度
地理数据 行政区划、商圈边界、POI 区域划分与半径投放

数据清洗流程

import pandas as pd
import geopandas as gpd

# 1. 加载原始数据
population = pd.read_csv("data/city_population.csv")
search_volume = pd.read_csv("data/regional_search_volume.csv")
competitors = pd.read_csv("data/competitor_locations.csv")

# 2. 地理编码标准化(统一行政区编码)
# 去除非标准地名,匹配到标准行政区代码
def standardize_region_name(name):
    """标准化区域名称"""
    replacements = {
        "广州市": "广州", "武汉市": "武汉", "深圳市": "深圳",
        "北京市": "北京", "上海市": "上海"
    }
    return replacements.get(name, name.replace("市", "").replace("省", ""))

population['region'] = population['city'].apply(standardize_region_name)
search_volume['region'] = search_volume['city'].apply(standardize_region_name)

# 3. 合并数据源
merged = population.merge(search_volume, on='region', how='left')
merged = merged.merge(
    competitors.groupby('region').size().reset_index(name='competitor_count'),
    on='region', how='left'
)

# 4. 缺失值处理
merged['competitor_count'] = merged['competitor_count'].fillna(0)
merged['search_volume'] = merged['search_volume'].fillna(0)

print(f"清洗完成: {len(merged)} 个区域")
print(merged[['region', 'population', 'search_volume', 'competitor_count']].head())

二、空间分析与区域潜力拆解

区域分层模型

国家层级
  └── 省级
       └── 市级
            └── 区/县级
                 └── 商圈/片区
                      └── 半径范围(1km/3km/5km)

区域潜力评分模型

def calculate_region_potential(df):
    """
    区域投放潜力评分
    评分公式:潜力 = (搜索量 × 人口密度) / (竞争度 + 1)
    """
    # 归一化处理
    df['search_norm'] = df['search_volume'] / df['search_volume'].max()
    df['pop_norm'] = df['population'] / df['population'].max()
    df['comp_norm'] = df['competitor_count'] / (df['competitor_count'].max() + 1)
    
    # 潜力评分(0-100)
    df['potential_score'] = (
        (df['search_norm'] * 0.4 + df['pop_norm'] * 0.3) / 
        (df['comp_norm'] + 0.3)
    ) * 100
    
    # 分级
    df['tier'] = pd.cut(
        df['potential_score'],
        bins=[0, 20, 40, 60, 80, 100],
        labels=['D', 'C', 'B', 'A', 'S']
    )
    
    return df.sort_values('potential_score', ascending=False)

# 执行评分
scored = calculate_region_potential(merged)
print(scored[['region', 'potential_score', 'tier']].head(20))

区域分级策略

等级 潜力评分 投放策略 预算占比
S 级 80-100 集中投放,最高出价 40%
A 级 60-80 重点投放,高出价 30%
B 级 40-60 均衡投放,标准出价 20%
C 级 20-40 测试投放,低出价 8%
D 级 0-20 暂停投放 2%

三、基于地理数据的投放方案

1. 预算拆分

def allocate_budget(total_budget, scored_df):
    """基于区域潜力评分分配预算"""
    budget_allocation = {
        'S': 0.40, 'A': 0.30, 'B': 0.20, 'C': 0.08, 'D': 0.02
    }
    
    scored_df['budget'] = 0.0
    for tier, ratio in budget_allocation.items():
        tier_regions = scored_df[scored_df['tier'] == tier]
        tier_budget = total_budget * ratio
        # 区域内按潜力评分等比分配
        if len(tier_regions) > 0:
            per_region = tier_budget / tier_regions['potential_score'].sum()
            scored_df.loc[scored_df['tier'] == tier, 'budget'] = \
                tier_regions['potential_score'] * per_region
    
    return scored_df

# 分配 100,000 元月预算
result = allocate_budget(100000, scored)
print(result[['region', 'tier', 'potential_score', 'budget']].head(15))

2. 人群拆分

不同区域的用户需求存在差异,需要差异化受众定位:

区域类型 受众特征 受众策略
一线城市 高收入、品牌敏感 品牌词 + 高端产品受众
二线城市 性价比导向 通用词 + 促销受众
产业聚集区 B2B 采购需求 行业词 + 决策者受众
本地商圈 到店转化 半径定位 + 本地居民受众

3. 产品拆分

# 基于区域需求匹配产品线
product_region_matrix = {
    '高端产品': ['S', 'A'],     # 仅在高潜力区域投放
    '标准产品': ['S', 'A', 'B'], # 中高潜力区域投放
    '入门产品': ['B', 'C'],      # 测试区域投放
    '清仓产品': ['C', 'D'],      # 低潜力区域清库存
}

def get_product_strategy(tier):
    """根据区域等级返回产品策略"""
    products = []
    for product, tiers in product_region_matrix.items():
        if tier in tiers:
            products.append(product)
    return products

# 示例
for tier in ['S', 'A', 'B', 'C', 'D']:
    print(f"{tier}级区域产品: {get_product_strategy(tier)}")

四、Google Ads 地域定位实操

地域设置

from google.ads.googleads.client import GoogleAdsClient

client = GoogleAdsClient.load_from_storage("google-ads.yaml")
campaign_criterion_service = client.get_service("CampaignCriterionService")

def set_geo_targeting(customer_id, campaign_id, location_ids, bid_adjustment=1.0):
    """设置广告系列地域定位
    
    Args:
        location_ids: Google Ads 地域 ID 列表
        bid_adjustment: 出价调整系数(1.2 = +20%)
    """
    operations = []
    
    for loc_id in location_ids:
        operation = client.get_type("CampaignCriterionOperation")
        criterion = operation.create
        criterion.campaign = f"customers/{customer_id}/campaigns/{campaign_id}"
        criterion.location.geo_target_constant = (
            f"geoTargetConstants/{loc_id}"
        )
        criterion.location.bid_multiplier = bid_adjustment
        operations.append(operation)
    
    response = campaign_criterion_service.mutate_campaign_criteria(
        customer_id=customer_id,
        operations=operations
    )
    print(f"已设置 {len(response.results)} 个地域定位")

# 中国主要城市 Google Ads 地域 ID
CITY_LOCATION_IDS = {
    "北京": 2151577,
    "上海": 2151849,
    "广州": 2151814,
    "深圳": 2151845,
    "杭州": 2151830,
    "武汉": 2151874,
    "成都": 2151730,
}

# S级城市出价 +20%,A级 +10%
set_geo_targeting("1234567890", "campaign_1", 
                  [CITY_LOCATION_IDS["广州"], CITY_LOCATION_IDS["深圳"]], 
                  bid_adjustment=1.2)

常用地域 ID 查询

def search_location_ids(customer_id, search_term):
    """搜索 Google Ads 地域 ID"""
    geo_service = client.get_service("GeoTargetConstantService")
    
    request = client.get_type("SearchGeoTargetConstantsRequest")
    request.query = search_term
    request.country_codes = ["CN"]  # 限定中国
    
    response = geo_service.search_geo_target_constants(request=request)
    
    for geo_target in response:
        print(f"{geo_target.geo_target_constant.id}: "
              f"{geo_target.geo_target_constant.name} "
              f"({geo_target.geo_target_constant.target_type})")

# 搜索广东省下的城市
search_location_ids("1234567890", "广东")

区域出价调整策略

区域等级 出价调整 说明
S 级(核心商圈) +20% ~ +50% 集中获取高价值流量
A 级(重点城市) +10% ~ +20% 稳定获取优质流量
B 级(潜力城市) 0%(标准) 保持基准出价
C 级(测试城市) -20% ~ -30% 低成本测试
D 级(低效城市) -50% 或排除 减少浪费

五、数据复盘与迭代

地域报告分析

def analyze_geo_performance(customer_id, days=30):
    """分析地域投放效果"""
    query = f"""
        SELECT
            segments.geo_target_city,
            segments.geo_target_country,
            metrics.impressions,
            metrics.clicks,
            metrics.cost_micros,
            metrics.conversions,
            metrics.conversions_value
        FROM campaign
        WHERE segments.date DURING LAST_{days}_DAYS
        ORDER BY metrics.cost_micros DESC
    """
    
    response = ga_service.search(customer_id=customer_id, query=query)
    
    data = []
    for row in response:
        data.append({
            'city_id': row.segments.geo_target_city,
            'impressions': row.metrics.impressions,
            'clicks': row.metrics.clicks,
            'cost': row.metrics.cost_micros / 1_000_000,
            'conversions': row.metrics.conversions,
            'cpa': row.metrics.cost_micros / row.metrics.conversions / 1_000_000 if row.metrics.conversions > 0 else float('inf')
        })
    
    df = pd.DataFrame(data)
    
    # 标记优化建议
    df['action'] = df.apply(lambda r: 
        '加预算' if r['cpa'] < 30 and r['conversions'] > 0
        else '降出价' if r['cpa'] > 100 and r['conversions'] > 0
        else '暂停' if r['clicks'] == 0 and r['impressions'] > 500
        else '观察', axis=1
    )
    
    return df

# 生成地域复盘报告
geo_report = analyze_geo_performance("1234567890", days=30)
print(geo_report.to_string(index=False))

迭代节奏

频率 动作
每日 监控 S/A 级区域花费与转化
每周 调整区域出价系数(±10%)
每月 全面地域复盘,更新潜力评分
每季度 重新评估区域分层,调整预算分配

相关文档


本板块持续更新中,最后更新:2026-06-29