def fetch_gsc_data(property_uri, start_date, end_date, creds):
service = build('searchconsole', 'v1', credentials=creds)
body = {
'startDate': start_date,
'endDate': end_date,
'dimensions': ['date'],
'rowLimit': 10000
}
response = service.searchanalytics().query(siteUrl=property_uri, body=body).execute()
rows = response.get('rows', [])
data = []
for r in rows:
d = r['keys'][0]
data.append({
'date': d,
'clicks': r.get('clicks', 0),
'impressions': r.get('impressions', 0),
'position': r.get('position', 0)
})
df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date'])
return df
def load_all_data(
start_date=START_DATE,
end_date=END_DATE,
sites=SITES,
creds_file="Название вашего JSON-файла"
):
creds = service_account.Credentials.from_service_account_file(
creds_file,
scopes=["https://www.googleapis.com/auth/webmasters.readonly"]
)
all_df = []
for s in sites:
df_s = fetch_gsc_data(s, start_date, end_date, creds)
df_s['domain'] = s
all_df.append(df_s)
big_df = pd.concat(all_df, ignore_index=True)
return big_df
app = dash.Dash(__name__)
GLOBAL_DF = None # кешируем загруженные данные
app.layout = html.Div([
html.H1("GSC Дашборд - Клики, Показы, Позиция"),
html.Div([
html.Label("Выберите сайт(-ы):"),
dcc.Checklist(
id='site-selector',
options=[{'label': site, 'value': site} for site in SITES],
value=SITES,
inline=True
),
]),
html.Div([
html.Label("Метрики:"),
dcc.Checklist(
id='metric-selector',
options=[
{'label': 'Клики', 'value': 'clicks'},
{'label': 'Показы', 'value': 'impressions'},
{'label': 'Позиция', 'value': 'position'},
],
# Если тут пусто, у нас нет рядов данных => ось X может стать [0..1]
value=[],
inline=True
),
]),
html.Div([
html.Label("Показать Google Updates:"),
dcc.Checklist(
id='updates-toggle',
options=[{'label': u['name'], 'value': u['name']} for u in GOOGLE_UPDATES],
value=[],
inline=True
),
]),
html.Div([
html.Label("Показать события:"),
dcc.Checklist(
id='events-toggle',
options=[{'label': e['name'], 'value': e['name']} for e in EVENTS],
value=[],
inline=True
),
]),
dcc.Graph(id='gsc-graph')
])
@app.callback(
Output('gsc-graph', 'figure'),
[
Input('site-selector', 'value'),
Input('metric-selector', 'value'),
Input('updates-toggle', 'value'),
Input('events-toggle', 'value'),
Input('gsc-graph', 'relayoutData')
]
)
def update_graph(selected_sites, selected_metrics, selected_updates, selected_events, relayoutData):
global GLOBAL_DF
if GLOBAL_DF is None:
GLOBAL_DF = load_all_data()
print("=== CALLBACK ===")
print("Selected events: ", selected_events) # Проверяем в консоли, что выбрано
fig = go.Figure()
# Фильтруем общий DF по выбранным доменам
filtered_df = GLOBAL_DF[GLOBAL_DF['domain'].isin(selected_sites)]
# Если выбраны метрики, строим линии
if selected_metrics:
for site in selected_sites:
df_site = filtered_df[filtered_df['domain'] == site].sort_values('date')
for metric in selected_metrics:
fig.add_trace(go.Scatter(
x=df_site['date'],
y=df_site[metric],
mode='lines',
name=f"{site} - {metric}"
))
Post #2338
439