feat(monitoring): attribute SaaS citations by registrable domain
Persist host/registrable_domain/site_key on monitoring article URL aliases, populate them on desktop-publish completion, and use them in the citation pipeline to count how often SaaS-published content appears as a citation source. Expose a /citation-summary endpoint with a 7/30-day window switch and surface the new source-share metrics in the tracking dashboard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,21 @@ func (h *MonitoringHandler) DashboardComposite(c *gin.Context) {
|
||||
response.Success(c, data)
|
||||
}
|
||||
|
||||
func (h *MonitoringHandler) CitationSummary(c *gin.Context) {
|
||||
days, err := parseOptionalInt(c.Query("days"))
|
||||
if err != nil {
|
||||
response.Error(c, response.ErrBadRequest(40031, "invalid_days", "days must be a number"))
|
||||
return
|
||||
}
|
||||
|
||||
data, svcErr := h.svc.CitationSummary(c.Request.Context(), days)
|
||||
if svcErr != nil {
|
||||
response.Error(c, svcErr)
|
||||
return
|
||||
}
|
||||
response.Success(c, data)
|
||||
}
|
||||
|
||||
func (h *MonitoringHandler) QuestionDetail(c *gin.Context) {
|
||||
brandID, err := strconv.ParseInt(c.Param("brand_id"), 10, 64)
|
||||
if err != nil {
|
||||
|
||||
@@ -183,6 +183,7 @@ func RegisterRoutes(app *bootstrap.App) {
|
||||
monitoring := tenantProtected.Group("/monitoring")
|
||||
monitoringHandler := NewMonitoringHandler(app)
|
||||
monitoring.GET("/dashboard/composite", monitoringHandler.DashboardComposite)
|
||||
monitoring.GET("/citation-summary", monitoringHandler.CitationSummary)
|
||||
monitoring.GET("/brands/:brand_id/questions/:question_id/detail", monitoringHandler.QuestionDetail)
|
||||
monitoring.POST("/brands/:brand_id/collect-now", monitoringHandler.CollectNow)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user