diff --git a/app/controllers/api/v1/accounts/lead_click_stats_controller.rb b/app/controllers/api/v1/accounts/lead_click_stats_controller.rb new file mode 100644 index 000000000..49077e41b --- /dev/null +++ b/app/controllers/api/v1/accounts/lead_click_stats_controller.rb @@ -0,0 +1,37 @@ +class Api::V1::Accounts::LeadClickStatsController < Api::V1::Accounts::BaseController + def index + clicks = account_clicks + total = clicks.count + convs = clicks.where.not(conversation_id: nil).count + + render json: { + total_clicks: total, + total_conversions: convs, + conversion_rate: total.positive? ? (convs.to_f / total * 100).round(1) : 0, + by_source: group_by(clicks, :source), + by_campaign: group_by(clicks, :campanha), + by_hostname: group_by(clicks, :hostname) + } + end + + private + + def account_clicks + LeadClick.joins(:inbox).where(inboxes: { account_id: current_account.id }) + end + + def group_by(clicks, column) + clicks + .group(column) + .select("#{column}, COUNT(*) AS clicks, COUNT(conversation_id) AS conversions") + .map do |r| + { + label: r.public_send(column).presence || '(sem nome)', + clicks: r.clicks, + conversions: r.conversions, + rate: r.clicks.positive? ? (r.conversions.to_f / r.clicks * 100).round(1) : 0 + } + end + .sort_by { |r| -r[:clicks] } + end +end diff --git a/app/controllers/api/v1/tracking_controller.rb b/app/controllers/api/v1/tracking_controller.rb index 228ef75f6..51eabfd7d 100644 --- a/app/controllers/api/v1/tracking_controller.rb +++ b/app/controllers/api/v1/tracking_controller.rb @@ -10,11 +10,12 @@ class Api::V1::TrackingController < ActionController::API private def resolved_inbox_id - LandingHost.find_by(hostname: params[:hostname].to_s.strip, active: true)&.inbox_id + host = params[:hostname].to_s.strip.sub(%r{^https?://}, '') + LandingHost.find_by(hostname: host, active: true)&.inbox_id end def click_params - { + base_params = { inbox_id: resolved_inbox_id, ip: params[:ip].presence || request.remote_ip, user_agent: request.user_agent || params[:user_agent], @@ -22,7 +23,22 @@ class Api::V1::TrackingController < ActionController::API source: params[:source], campanha: params[:campanha], lp: params[:lp], + click_id: params[:click_id], status: :clicked } + + # Se 'lp' for fornecido, extraímos os UTMs se fonte ou campanha estiverem vazios + if base_params[:lp].present? + begin + uri = URI.parse(base_params[:lp]) + query = Rack::Utils.parse_nested_query(uri.query) + base_params[:source] ||= query['utm_source'] + base_params[:campanha] ||= query['utm_campaign'] + rescue StandardError => e + Rails.logger.warn("Error parsing LP URL for UTMs: #{e.message}") + end + end + + base_params end end diff --git a/app/javascript/dashboard/i18n/locale/en/captain.json b/app/javascript/dashboard/i18n/locale/en/captain.json index ea724918f..f0bdf1ded 100644 --- a/app/javascript/dashboard/i18n/locale/en/captain.json +++ b/app/javascript/dashboard/i18n/locale/en/captain.json @@ -394,7 +394,23 @@ "TABS": { "DASHBOARD": "Dashboard", "INSIGHTS": "AI Insights", - "OPERATIONAL": "Operational" + "OPERATIONAL": "Operational", + "LANDING_PAGES": "Landing Pages" + }, + "LP": { + "LOADING": "Loading data...", + "NO_DATA": "No clicks recorded yet. Integrate the pixel on your landing page to see data here.", + "TOTAL_CLICKS": "Total Clicks", + "TOTAL_CONVERSIONS": "Conversions (WhatsApp)", + "CONVERSION_RATE": "Conversion Rate", + "BY_SOURCE": "Clicks by Source", + "BY_CAMPAIGN": "Clicks by Campaign", + "BY_HOSTNAME": "Clicks by Landing Page", + "CLICKS": "clicks", + "CONV": "conv", + "REFRESH": "Refresh", + "LEGEND_CLICKS": "Clicks", + "LEGEND_CONVERSIONS": "Conversions" }, "FILTER_DATE": { "LABEL": "Period:", diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json index 78c0a4938..89f6c6f60 100644 --- a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json +++ b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json @@ -395,7 +395,23 @@ "TABS": { "DASHBOARD": "Dashboard", "INSIGHTS": "Insights IA", - "OPERATIONAL": "Operacional" + "OPERATIONAL": "Operacional", + "LANDING_PAGES": "Landing Pages" + }, + "LP": { + "LOADING": "Carregando dados...", + "NO_DATA": "Nenhum clique registrado ainda. Integre o pixel na landing page para ver os dados aqui.", + "TOTAL_CLICKS": "Total de Cliques", + "TOTAL_CONVERSIONS": "Conversões (WhatsApp)", + "CONVERSION_RATE": "Taxa de Conversão", + "BY_SOURCE": "Cliques por Origem", + "BY_CAMPAIGN": "Cliques por Campanha", + "BY_HOSTNAME": "Cliques por Landing Page", + "CLICKS": "cliques", + "CONV": "conv", + "REFRESH": "Atualizar", + "LEGEND_CLICKS": "Cliques", + "LEGEND_CONVERSIONS": "Conversões" }, "FILTER_DATE": { "LABEL": "Período:", diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/reports/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/captain/reports/Index.vue index 6c26b7b8c..48c3f119c 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/captain/reports/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/reports/Index.vue @@ -1,4 +1,5 @@