Casino SEO Builder
Войди чтобы продолжить
SEO Проекты
Нет проектов
🌍 Регионы
Выбери проект
🔑 Ключи:
Выбери регион
⚡ Прокликивание
МАССОВОЕ ПРОКЛИКИВАНИЕ
Лог...
Позиции:
Ключ Тип Поз. Частот. URL Дата
Выбери проект и нажми Снять позиции
🖱️ ПФ:
00 / 0
Ключ Хвост Тип Кл/д Стат Действия
Выбери проект и регион
Бренды казино
Загрузка...
Настройки
Яндекс аккаунты
Загрузка...
Поиск доменов
Запуск
Нажми Запустить...
`; document.getElementById('design-preview-frame').srcdoc = preview_html; } async function deleteDesign(id) { if (!confirm('Удалить дизайн?')) return; await apiFetch('/designs/'+id, {method:'DELETE'}); notify('Дизайн удалён', 'success'); loadDesigns(); } function openUploadCssModal() { openModal('upload-css-modal'); } function openAiDesignModal() { openModal('ai-design-modal'); } async function uploadCssFile() { const nameEl = document.getElementById('css-upload-name'); const descEl = document.getElementById('css-upload-desc'); const fileEl = document.getElementById('css-upload-file'); const name = nameEl.value.trim(); const file = fileEl.files[0]; if (!name) { notify('Введи название', 'error'); return; } if (!file) { notify('Выбери CSS файл', 'error'); return; } if (!file.name.endsWith('.css')) { notify('Только .css файлы', 'error'); return; } const fd = new FormData(); fd.append('file', file); fd.append('name', name); fd.append('description', descEl.value.trim()); const r = await fetch('/api/designs/upload-css', { method:'POST', headers:{'Authorization':'Bearer '+localStorage.getItem('token')}, body:fd }); const d = await r.json(); if (r.ok && d.success) { notify('✅ CSS загружен!', 'success'); closeModal('upload-css-modal'); nameEl.value=''; descEl.value=''; fileEl.value=''; loadDesigns(); } else { notify('❌ ' + (d.detail || 'Ошибка'), 'error'); } } async function generateAiDesign() { const styleEl = document.getElementById('ai-design-style'); const nameEl = document.getElementById('ai-design-name'); const style = styleEl?.value || 'casino-gold'; const name = nameEl?.value?.trim() || style; const btn = document.getElementById('ai-design-btn'); btn.textContent = '⏳ Генерирую CSS...'; btn.disabled = true; notify('🎨 AI пишет CSS тему...', 'info'); const r = await apiFetch('/design-generate', { method:'POST', body: JSON.stringify({ style, name, save: true }) }); btn.textContent = '✨ Сгенерировать'; btn.disabled = false; const d = await r?.json(); if (d?.success) { notify(`✅ Тема "${name}" создана! ${d.css_length} символов CSS`, 'success'); closeModal('ai-design-modal'); if (nameEl) nameEl.value = ''; loadDesigns(); // Открываем превью setTimeout(() => sitraPreviewTheme(style), 500); } else { notify('❌ ' + (d?.detail || 'Ошибка генерации'), 'error'); } } async function applyDesignTheme(style) { const r = await apiFetch('/design-apply', {method:'POST', body:JSON.stringify({style})}); const d = await r?.json(); if (d?.success) { notify(`✅ Тема "${style}" будет использована при следующей сборке`, 'success'); } else { notify('❌ ' + (d?.detail || 'Ошибка'), 'error'); } } async function sitraPreviewTheme(style) { const frame = document.getElementById('design-preview-frame'); if (!frame) return; const r = await apiFetch(`/design-preview/${style}`); if (r?.ok) { const html = await r.text(); frame.srcdoc = html; } } (async()=>{const ok=await checkAuth();if(ok)init();})(); // ── УПРАВЛЕНИЕ КЛИКАМИ ───────────────────────────────────────────────────────── function setKwClicks(keyword, value){ kwClicksMap[keyword] = parseInt(value) || 16; // Сохраняем в localStorage try { localStorage.setItem('kwClicks_'+btoa(encodeURIComponent(keyword)), value); } catch(e){} } function loadKwClicks(){ // Загружаем сохранённые значения try { for(let i=0;iv)) document.getElementById('stop-all-btn').style.display='none'; if(d){ const res = d.results?.[0]; const clicked = res?.clicked || false; const profile = res?.profile ? ' ['+res.profile+']' : ''; log.textContent = keyword + ': ' + (clicked?'✅':'❌') + profile; notify(clicked ? '✅ Прокликано: '+keyword : '❌ Не найден: '+keyword, clicked?'success':'error'); updateKwStat(keyword, clicked); const sc=document.getElementById('stat-clicked'); const sm=document.getElementById('stat-missed'); const st=document.getElementById('stat-total'); if(sc&&sm&&st){ if(clicked) sc.textContent=parseInt(sc.textContent||0)+1; else sm.textContent=parseInt(sm.textContent||0)+1; st.textContent=parseInt(st.textContent||0)+1; } } } async function runAiClickAnalysis(){ if(selectedMonitorProject===null) return; const proj = monitorProjects[selectedMonitorProject]; if(!proj) return; const limit = parseInt(document.getElementById('click-limit-day').value) || 150; const positions = positionsData.filter(p => p.keyword); if(!positions.length){ notify('ИИ: сначала проверь позиции','error'); return; } const posInfo = positions.map(p => `${p.keyword}: позиция ${p.found ? p.position : 'не найден'} (${p.freq_type||'НЧ'})` ).join('\n'); const prompt = `Ты SEO специалист по продвижению казино сайтов в Яндексе. Сайт: ${proj.domain} Регион: Москва Тематика: онлайн казино (высококонкурентная) Текущие позиции: ${posInfo} Общий лимит кликов в сутки: ${limit} По документации PF сервиса для гемблинга нужно 15-30+ кликов в день на запрос. Распредели ${limit} кликов между ключами. Учти: - ВЧ запросы в позициях 10-50: давать больше кликов - ВЧ запросы в топ-5: поддерживающий режим (меньше кликов) - НЧ в топ-3: минимум кликов - Не найденные: средний объём для буста Ответь ТОЛЬКО в формате JSON без markdown: {"analysis": "краткий анализ", "keywords": [{"word": "ключ", "clicks_per_day": 20, "priority": "high/medium/low"}]}`; notify('🤖 ИИ анализирует позиции...','info'); document.getElementById('click-log').textContent = '🤖 ИИ думает...'; try{ const r = await apiFetch('/chat', {method:'POST', body:JSON.stringify({message: prompt, system: 'Ты SEO эксперт. Отвечай только JSON.'})}); const d = await r?.json(); const text = d?.response || d?.message || ''; const clean = text.replace(/```json|```/g,'').trim(); const result = JSON.parse(clean); document.getElementById('click-log').textContent = '🤖 ' + (result.analysis||'Анализ готов'); // Показываем рекомендации if(result.keywords?.length){ const total = result.keywords.reduce((s,k)=>s+k.clicks_per_day,0); notify(`🤖 ИИ: распределил ${total} кликов по ${result.keywords.length} ключам`, 'success'); // Сохраняем рекомендации в проект monitorProjects[selectedMonitorProject]._ai_clicks = result.keywords; monitorProjects[selectedMonitorProject]._ai_analysis = result.analysis; } } catch(e){ document.getElementById('click-log').textContent = '❌ ИИ ошибка: ' + e.message; notify('ИИ ошибка','error'); } } async function bulkClickWithLimit(){ const limit = parseInt(document.getElementById('click-limit-day').value) || 150; const interval = parseInt(document.getElementById('click-interval').value) || 30; if(clickMode === 'ai' && selectedMonitorProject !== null){ const proj = monitorProjects[selectedMonitorProject]; if(proj?._ai_clicks?.length){ notify(`🤖 ИИ запускает ${proj._ai_clicks.length} кликов...`, 'info'); // Запускаем по рекомендациям ИИ for(const kw of proj._ai_clicks){ await clickOneKeyword(kw.word); await new Promise(r=>setTimeout(r, interval * 60 * 1000 / proj._ai_clicks.length)); } return; } } } // ── XMLSTOCK НАСТРОЙКИ ───────────────────────────────────────────────────────── async function openXmlstockModal(){ // Загружаем текущие настройки try{ const r = await apiFetch('/settings'); const d = await r?.json(); if(d){ document.getElementById('xs-user').value = d.xmlstock_user || ''; document.getElementById('xs-key').value = d.xmlstock_key || ''; document.getElementById('xr-user').value = d.xmlriver_user || ''; document.getElementById('xr-key').value = d.xmlriver_key || ''; } } catch(e){} openModal('xmlstock-modal'); } async function saveXmlstockSettings(){ const data = { xmlstock_user: document.getElementById('xs-user').value.trim(), xmlstock_key: document.getElementById('xs-key').value.trim(), xmlriver_user: document.getElementById('xr-user').value.trim(), xmlriver_key: document.getElementById('xr-key').value.trim(), }; const r = await apiFetch('/settings', {method:'POST', body:JSON.stringify(data)}); if(r?.ok){ notify('✅ XMLStock настройки сохранены', 'success'); closeModal('xmlstock-modal'); } } async function testXmlstock(){ const user = document.getElementById('xs-user').value.trim(); const key = document.getElementById('xs-key').value.trim(); const el = document.getElementById('xs-test-result'); if(!user || !key){ el.textContent = '❌ Заполни User ID и API Key'; el.style.color='var(--red)'; return; } el.textContent = '⏳ Тестируем...'; el.style.color='var(--text2)'; const r = await apiFetch('/monitor/test-xmlstock?user='+user+'&key='+key); const d = await r?.json(); if(d?.success){ el.textContent = '✅ Работает! Найдено позиций: ' + (d.position || 'проверено'); el.style.color = 'var(--green)'; } else { el.textContent = '❌ Ошибка: ' + (d?.error || 'неизвестно'); el.style.color = 'var(--red)'; } } // ── РЕГИОНЫ ЯНДЕКСА ─────────────────────────────────────────────────────────── function filterRegions(query){ const dd = document.getElementById('region-dropdown'); if(!query){ showRegionDropdown(); return; } const q = query.toLowerCase(); const filtered = YANDEX_REGIONS_ALL.filter(r=>r.name.toLowerCase().includes(q)); renderRegionDropdown(filtered); } function showRegionDropdown(){ renderRegionDropdown(YANDEX_REGIONS_ALL); } function hideRegionDropdown(){ const dd = document.getElementById('region-dropdown'); if(dd) dd.style.display='none'; } function renderRegionDropdown(regions){ const dd = document.getElementById('region-dropdown'); if(!dd) return; dd.style.display = 'block'; dd.innerHTML = regions.slice(0,20).map(r=> `
${r.flag}${r.name} lr=${r.id}
` ).join(''); } function selectRegion(key, name){ selectedRegionKey = key; document.getElementById('monitor-region-select').value = key; document.getElementById('monitor-region-input').value = name; hideRegionDropdown(); updateRegionLabel(); if(selectedMonitorProject!==null) renderKeywordsAsPositions(monitorProjects[selectedMonitorProject]); } // Инициализация региона document.addEventListener('DOMContentLoaded', ()=>{ const inp = document.getElementById('monitor-region-input'); if(inp) inp.value = 'Москва'; }); // ── ЧАСТОТНОСТЬ XMLRiver ─────────────────────────────────────────────────────── async function loadFrequency(keywords){ try{ const r = await apiFetch('/monitor/frequency', { method:'POST', body: JSON.stringify({keywords, region_id: YANDEX_REGIONS_ALL.find(r=>r.key===selectedRegionKey)?.id || '213'}) }); if(!r?.ok) return {}; return await r.json(); } catch(e){ return {}; } } // ── СТАТИСТИКА КЛИКОВ ───────────────────────────────────────────────────────── function updateKwStat(keyword, success){ if(!kwStats[keyword]) kwStats[keyword] = {ok:0, err:0}; if(success) kwStats[keyword].ok++; else kwStats[keyword].err++; // Обновляем UI const key = keyword.replace(/\s/g,'_'); const ok = document.getElementById('kstat_ok_'+key); const err = document.getElementById('kstat_err_'+key); if(ok) ok.textContent = kwStats[keyword].ok; if(err) err.textContent = kwStats[keyword].err; } function stopKeyword(keyword){ activeClicks[keyword] = false; const key = keyword.replace(/\s/g,'_'); const btn = document.getElementById('stop_'+key); if(btn) btn.style.display='none'; notify('⏹ Остановлено: '+keyword, 'info'); } function stopAllClicks(){ stopRequested = true; Object.keys(activeClicks).forEach(k=>activeClicks[k]=false); document.getElementById('stop-all-btn').style.display='none'; notify('⏹ Все клики остановлены','info'); } // ── РЕГИОН В ПОЗИЦИЯХ ───────────────────────────────────────────────────────── function updateRegionLabel(){ const region = YANDEX_REGIONS_ALL.find(r=>r.key===(document.getElementById('monitor-region-select')?.value||'moskva')); const name = region?.name || 'Москва'; const el1 = document.getElementById('positions-region-label'); const el2 = document.getElementById('stat-region'); if(el1) el1.textContent = name; if(el2) el2.textContent = name; } // Добавляем мультирегионы в левую панель ключевых слов async function addRegionToProject(reg){ if(selectedMonitorProject===null){notify('Выбери проект','error');return;} const region = reg || YANDEX_REGIONS_ALL.find(r=>r.key===(document.getElementById('monitor-region-select')?.value||'moskva')); if(!region) return; const proj = monitorProjects[selectedMonitorProject]; if(proj.regions && proj.regions.find(r=>r.key===region.key)){notify('Регион уже добавлен','info');return;} const r=await apiFetch('/monitor/projects/'+selectedMonitorProject+'/regions',{ method:'POST',body:JSON.stringify({region:{key:region.key,name:region.name,id:region.id,flag:region.flag||'🌍',keywords:[],clicks_per_day:150}}) }); if(r?.ok){ const d=await r.json(); monitorProjects[selectedMonitorProject]=d; renderProjectRegionTabs(d); renderMonitorProjects(); notify('Регион '+region.name+' добавлен','success'); }else{ notify('Ошибка при добавлении региона','error'); } } function renderProjectRegions(proj){ const el = document.getElementById('project-regions-list'); if(!el) return; // Фильтруем невалидные регионы let regions = (proj.regions || []).filter(r=>r && r.key && r.name && r.key !== 'undefined'); if(!regions.length) regions = [{key:'moskva', name:'Москва', id:'213'}]; el.innerHTML = regions.map(r=>`
`).join(''); } function selectProjectRegion(key, name){ document.getElementById('monitor-region-select').value = key; document.getElementById('monitor-region-input').value = name; updateRegionLabel(); // Показываем ключи для этого региона if(selectedMonitorProject!==null){ renderKeywordsAsPositions(monitorProjects[selectedMonitorProject]); } } async function deleteKeyword(kwIdx){ if(selectedMonitorProject===null) return; const r = await apiFetch('/monitor/projects/'+selectedMonitorProject+'/keywords/'+kwIdx, {method:'DELETE'}); if(r?.ok){ const d = await r.json(); monitorProjects[selectedMonitorProject] = d; renderProjectKeywords(d); renderKeywordsAsPositions(d); notify('✅ Ключ удалён','success'); } } async function saveProjectRegions(){ if(selectedMonitorProject===null) return; const proj = monitorProjects[selectedMonitorProject]; const regions = proj.regions || []; const r = await apiFetch('/monitor/projects/'+selectedMonitorProject+'/regions', { method:'POST', body: JSON.stringify({regions}) }); if(r?.ok) notify('✅ Регионы сохранены','success'); } async function addRegionToProjectAndSave(){ if(selectedMonitorProject===null){notify('Выбери проект','error');return;} const regionKey = document.getElementById('monitor-region-select')?.value || 'moskva'; const region = YANDEX_REGIONS_ALL.find(r=>r.key===regionKey); if(!region) return; const proj = monitorProjects[selectedMonitorProject]; if(!proj.regions) proj.regions = [{key:'moskva',name:'Москва',id:'213'}]; if(!proj.regions.find(r=>r.key===region.key)){ proj.regions.push({key:region.key, name:region.name, id:region.id}); await saveProjectRegions(); renderProjectRegions(proj); renderMonitorProjects(); notify('✅ '+region.name+' добавлен','success'); } else { notify('Регион уже есть','info'); } } async function removeRegion(key){ if(selectedMonitorProject===null) return; const proj = monitorProjects[selectedMonitorProject]; proj.regions = (proj.regions||[]).filter(r=>r && r.key && r.key!==key && r.key!=='undefined'); if(!proj.regions.length) proj.regions = [{key:'moskva',name:'Москва',id:'213',flag:'🏙️'}]; await saveProjectRegions(); renderProjectRegions(proj); renderMonitorProjects(); } async function deleteKeywordByWord(word){ if(selectedMonitorProject===null) return; if(!confirm('Удалить ключ: '+word+'?')) return; const proj = monitorProjects[selectedMonitorProject]; const idx = (proj.keywords||[]).findIndex(k=>(typeof k==='string'?k:k.word)===word); if(idx===-1){notify('Ключ не найден','error');return;} const r = await apiFetch('/monitor/projects/'+selectedMonitorProject+'/keywords/'+idx, {method:'DELETE'}); if(r?.ok){ const d = await r.json(); monitorProjects[selectedMonitorProject] = d; renderProjectKeywords(d); renderKeywordsAsPositions(d); renderMonitorProjects(); notify('✅ Ключ удалён','success'); } } // Обновлённая stopKeyword — меняет иконку на ▶️ для возобновления function stopKeyword(keyword){ const key = keyword.replace(/[^a-zA-Zа-яА-Я0-9]/g,'_'); if(activeClicks[keyword]){ activeClicks[keyword] = false; const stopBtn = document.getElementById('stop_'+key); const clickBtn = document.getElementById('click_btn_'+key); if(stopBtn) stopBtn.style.display='none'; if(clickBtn) clickBtn.style.opacity='1'; notify('⏸ Остановлено: '+keyword,'info'); } }
📥 Manual DNS — ручной импорт доменов
Уже зарегистрированные домены/поддомены. 1reg не вызывается.
Формат: domain | kind | brand_slug_or_intent
Пример: lakibir.casino.xn--6frz82g | brand | lakibir
Очередь доменов
#ДоменТипБренд/ИнтентTarget IPСтатусПроект
Нажми «Обновить»

Vercel / GoGate

Managed Vercel sites + GoGate redirect gateway
Vercel sites (live)
Loading...
GoGate gateway
Loading...
Gateway URL: https://allzerkal-302.top/r · Sync: · Last export:
Brands
BrandModeIntentURLActions
Loading...
Vercel site rules
SiteBrandModeURLActions
Loading...
Test route

  
Emergency controls

  

🏗️ Vercel Factory v2

Brand builder, generic topics, build-preview. Деплой отключён.
⚠️ Реальный деплой отключён. Только draft и preview. Для live-деплоя нужен отдельный STEP.
-
Бренды + темы
-
Casino brands
-
Generic topics
-
Intents
Build-preview
ENABLED
Real deploy
DISABLED
📋 Реестр сайтов Vercel
Live сайты · статус · SEO · GoGate
Slug / URL Бренд Intent Батч SEO Metrika Verify /go Дата Действия
Загрузка реестра...
🔀 Редиректы /go
Режимы маршрутов · GoGate · Runewall sync
Сайт Бренд Режим /go Партнёр Действия
Загрузка маршрутов...
Бренды / Темы
SlugНазваниеTypeStatusAliasesLogo
Loading...
🏗️ Создать новый сайт
Media packs: loading...

  
SEO Content
⚠️ Real AI выключен — mock_unique/manual preview
Секции
Сеед не сохранён
Ждём запроса...