Documentation
¶
Index ¶
- Constants
- Variables
- func BadRequest(w http.ResponseWriter, r *http.Request, message string)
- func CORSMiddleware(next http.Handler) http.Handler
- func CrossOriginProtectionMiddleware(next http.Handler) http.Handler
- func DatabaseError(w http.ResponseWriter, r *http.Request, err error)
- func Forbidden(w http.ResponseWriter, r *http.Request, message string)
- func GetMetricsMetadata() map[string]MetricInfo
- func GetRequestID(r *http.Request) string
- func HandlePoolSaturation(w http.ResponseWriter, r *http.Request, err error) bool
- func InternalError(w http.ResponseWriter, r *http.Request, err error)
- func LoggingMiddleware(next http.Handler) http.Handler
- func MethodNotAllowed(w http.ResponseWriter, r *http.Request)
- func NotFound(w http.ResponseWriter, r *http.Request, message string)
- func RequestIDMiddleware(next http.Handler) http.Handler
- func SecurityHeadersMiddleware(next http.Handler) http.Handler
- func ServiceUnavailable(w http.ResponseWriter, r *http.Request, message string)
- func TooManyRequests(w http.ResponseWriter, r *http.Request, message string, ...)
- func Unauthorised(w http.ResponseWriter, r *http.Request, message string)
- func WriteCreated(w http.ResponseWriter, r *http.Request, data any, message string)
- func WriteError(w http.ResponseWriter, r *http.Request, err error, status int, code ErrorCode)
- func WriteErrorMessage(w http.ResponseWriter, r *http.Request, message string, status int, ...)
- func WriteHealthy(w http.ResponseWriter, r *http.Request, service string, version string)
- func WriteJSON(w http.ResponseWriter, r *http.Request, data any, status int)
- func WriteNoContent(w http.ResponseWriter, r *http.Request)
- func WriteSuccess(w http.ResponseWriter, r *http.Request, data any, message string)
- func WriteUnhealthy(w http.ResponseWriter, r *http.Request, service string, err error)
- type AuthProfileUpdateRequest
- type AuthRegisterRequest
- type AuthSessionRequest
- type BrokerCleaner
- type CreateDomainRequest
- type CreateJobRequest
- type CreateOrganisationRequest
- type DBClient
- type DBInterfaceGA4
- type DomainResponse
- type ErrorCode
- type ErrorResponse
- type ExportColumn
- type GA4APIError
- type GA4Account
- type GA4AccountResponse
- type GA4Client
- func (c *GA4Client) FetchTopPages(ctx context.Context, propertyID string, limit, offset int, ...) ([]PageViewData, error)
- func (c *GA4Client) FetchTopPagesWithRetry(ctx context.Context, propertyID, refreshToken string, limit, offset int, ...) ([]PageViewData, error)
- func (c *GA4Client) RefreshAccessToken(ctx context.Context, refreshToken string) (string, error)
- type GA4Property
- type GoogleConnectionResponse
- type GoogleTokenResponse
- type GoogleUserInfo
- type Handler
- func (h *Handler) AdminReclaimRedis(w http.ResponseWriter, r *http.Request)
- func (h *Handler) AdminResetData(w http.ResponseWriter, r *http.Request)
- func (h *Handler) AdminResetDatabase(w http.ResponseWriter, r *http.Request)
- func (h *Handler) AuthProfile(w http.ResponseWriter, r *http.Request)
- func (h *Handler) AuthRegister(w http.ResponseWriter, r *http.Request)
- func (h *Handler) AuthSession(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DashboardActivity(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DashboardExternalRedirects(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DashboardSlowPages(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DashboardStats(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DatabaseHealthCheck(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DevAutoLogin(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DomainsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) GetAccountProperties(w http.ResponseWriter, r *http.Request, googleAccountID string)
- func (h *Handler) GetActiveOrganisation(w http.ResponseWriter, r *http.Request) string
- func (h *Handler) GetActiveOrganisationWithUser(w http.ResponseWriter, r *http.Request) (*db.User, string, bool)
- func (h *Handler) GoogleConnectionHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) GoogleConnectionsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) HandleGoogleOAuthCallback(w http.ResponseWriter, r *http.Request)
- func (h *Handler) HandleWebflowOAuthCallback(w http.ResponseWriter, r *http.Request)
- func (h *Handler) HealthCheck(w http.ResponseWriter, r *http.Request)
- func (h *Handler) InitiateGoogleOAuth(w http.ResponseWriter, r *http.Request)
- func (h *Handler) InitiateWebflowOAuth(w http.ResponseWriter, r *http.Request)
- func (h *Handler) JobHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) JobsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ListGA4Accounts(w http.ResponseWriter, r *http.Request)
- func (h *Handler) MetadataHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) NotificationHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) NotificationsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) NotificationsReadAllHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationInviteAcceptHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationInviteHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationInvitePreviewHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationInvitesHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationMemberHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationMembersHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationPlanHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) OrganisationsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) PlansHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) RefreshGA4Accounts(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SaveGA4AccountProperties(w http.ResponseWriter, r *http.Request, googleAccountID string)
- func (h *Handler) SaveGoogleProperties(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SaveGoogleProperty(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SchedulerHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SchedulersHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeAuthCallback(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeAuthModal(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeConfigJS(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeDashboard(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeDebugAuth(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeExtensionAuth(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeHomepage(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeInviteWelcome(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeJobDetails(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeNewDashboard(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeSettings(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeSharedJobPage(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeTestComponents(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeTestDataComponents(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeTestLogin(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ServeWelcome(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SetupRoutes(mux *http.ServeMux)
- func (h *Handler) SharedJobHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SlackConnectionHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SlackConnectionsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SlackOAuthCallback(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SwitchOrganisationHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) UpdateGoogleConnection(w http.ResponseWriter, r *http.Request, connectionID string)
- func (h *Handler) UpdateGooglePropertyStatus(w http.ResponseWriter, r *http.Request, connectionID string)
- func (h *Handler) UsageHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) UsageHistoryHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) WebflowConnectionHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) WebflowConnectionsHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) WebflowSitesHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) WebflowWebhook(w http.ResponseWriter, r *http.Request)
- type HealthResponse
- type JobActionRequest
- type JobResponse
- type MetricInfo
- type NotificationResponse
- type NotificationsListResponse
- type OAuthState
- type OrganisationResponse
- type PageViewData
- type PendingGASession
- type ProgressiveFetcher
- type PublicPlan
- type SchedulerRequest
- type SchedulerResponse
- type SlackConnectRequest
- type SlackConnectResponse
- type SlackConnectionResponse
- type SlackLinkUserRequest
- type SlackUpdateNotificationsRequest
- type SlackUserLinkResponse
- type SuccessResponse
- type SwitchOrganisationRequest
- type TaskQueryBuilder
- type TaskQueryParams
- type TaskResponse
- type UpdateAutoPublishRequest
- type UpdateOrganisationMemberRoleRequest
- type UpdateScheduleRequest
- type UserResponse
- type WebflowAuthInfo
- type WebflowConnectionResponse
- type WebflowCustomDomain
- type WebflowSite
- type WebflowSiteSettingResponse
- type WebflowSitesListResponse
- type WebflowSitesResponse
- type WebflowTokenResponse
- type WebflowUserInfo
- type WebflowWebhookPayload
Constants ¶
const ( // GA4InitialBatchSize is the first batch of pages fetched GA4InitialBatchSize = 100 // GA4MediumBatchSize is used for subsequent fetches after the initial batch GA4MediumBatchSize = 1000 // GA4LargeBatchSize is the maximum batch size for bulk fetching // GA4 API supports up to 250,000 rows per request GA4LargeBatchSize = 50000 // GA4MediumBatchThreshold is the offset at which we switch from medium to large batches GA4MediumBatchThreshold = 10000 // Date range lookback periods for analytics queries GA4Lookback7Days = 7 GA4Lookback28Days = 28 GA4Lookback180Days = 180 )
GA4 API limits and constraints
Variables ¶
var Version = "0.4.1"
Set via ldflags at build time.
Functions ¶
func BadRequest ¶
func BadRequest(w http.ResponseWriter, r *http.Request, message string)
func CORSMiddleware ¶
CORSMiddleware adds CORS headers for browser requests
func CrossOriginProtectionMiddleware ¶
CrossOriginProtectionMiddleware provides protection against CSRF attacks. It is a wrapper around Go's experimental http.CrossOriginProtection.
func DatabaseError ¶
func DatabaseError(w http.ResponseWriter, r *http.Request, err error)
func GetMetricsMetadata ¶
func GetMetricsMetadata() map[string]MetricInfo
GetMetricsMetadata returns metadata for all dashboard metrics
func GetRequestID ¶
GetRequestID retrieves the request ID from the request context
func HandlePoolSaturation ¶
Returns true and writes a 429 when err indicates pool exhaustion.
func InternalError ¶
func InternalError(w http.ResponseWriter, r *http.Request, err error)
func LoggingMiddleware ¶
LoggingMiddleware logs request details and response times
func MethodNotAllowed ¶
func MethodNotAllowed(w http.ResponseWriter, r *http.Request)
func RequestIDMiddleware ¶
RequestIDMiddleware adds a unique request ID to each request
func SecurityHeadersMiddleware ¶
SecurityHeadersMiddleware adds security-related headers
func ServiceUnavailable ¶
func ServiceUnavailable(w http.ResponseWriter, r *http.Request, message string)
func TooManyRequests ¶
func TooManyRequests(w http.ResponseWriter, r *http.Request, message string, retryAfter time.Duration)
Sets Retry-After header.
func Unauthorised ¶
func Unauthorised(w http.ResponseWriter, r *http.Request, message string)
func WriteCreated ¶
WriteCreated writes a standardised success response for created resources
func WriteError ¶
func WriteErrorMessage ¶
func WriteHealthy ¶
WriteHealthy writes a standardised health check response
func WriteNoContent ¶
func WriteNoContent(w http.ResponseWriter, r *http.Request)
WriteNoContent writes a 204 No Content response
func WriteSuccess ¶
WriteSuccess writes a standardised success response
func WriteUnhealthy ¶
WriteUnhealthy writes a standardised unhealthy response
Types ¶
type AuthRegisterRequest ¶
type AuthRegisterRequest struct {
UserID string `json:"user_id"`
Email string `json:"email"`
FirstName *string `json:"first_name,omitempty"`
LastName *string `json:"last_name,omitempty"`
FullName *string `json:"full_name,omitempty"`
OrgName *string `json:"org_name,omitempty"`
}
AuthRegisterRequest represents a user registration request
type AuthSessionRequest ¶
type AuthSessionRequest struct {
Token string `json:"token"`
}
AuthSessionRequest represents a session validation request
type BrokerCleaner ¶ added in v0.33.10
type CreateDomainRequest ¶
type CreateDomainRequest struct {
Domain string `json:"domain"`
}
CreateDomainRequest represents the request body for POST /v1/domains
type CreateJobRequest ¶
type CreateJobRequest struct {
Domain string `json:"domain"`
UseSitemap *bool `json:"use_sitemap,omitempty"`
FindLinks *bool `json:"find_links,omitempty"`
AllowCrossSubdomainLinks *bool `json:"allow_cross_subdomain_links,omitempty"`
Concurrency *int `json:"concurrency,omitempty"`
MaxPages *int `json:"max_pages,omitempty"`
SourceType *string `json:"source_type,omitempty"`
SourceDetail *string `json:"source_detail,omitempty"`
SourceInfo *string `json:"source_info,omitempty"`
}
CreateJobRequest represents the request body for creating a job
type CreateOrganisationRequest ¶
type CreateOrganisationRequest struct {
Name string `json:"name"`
}
CreateOrganisationRequest represents the request to create an organisation
type DBClient ¶
type DBClient interface {
GetDB() *sql.DB
GetOrCreateUser(userID, email string, orgID *string) (*db.User, error)
GetJobStats(organisationID string, startDate, endDate *time.Time) (*db.JobStats, error)
GetJobActivity(organisationID string, startDate, endDate *time.Time) ([]db.ActivityPoint, error)
GetSlowPages(organisationID string, startDate, endDate *time.Time) ([]db.SlowPage, error)
GetExternalRedirects(organisationID string, startDate, endDate *time.Time) ([]db.ExternalRedirect, error)
GetUserByWebhookToken(token string) (*db.User, error)
GetUser(userID string) (*db.User, error)
UpdateUserNames(userID string, firstName, lastName, fullName *string) error
ResetSchema() error
ResetDataOnly() error
CreateUser(userID, email string, firstName, lastName, fullName *string, orgName string) (*db.User, *db.Organisation, error)
GetOrganisation(organisationID string) (*db.Organisation, error)
ListJobs(organisationID string, limit, offset int, status, dateRange, timezone string) ([]db.JobWithDomain, int, error)
ListJobsWithOffset(organisationID string, limit, offset int, status, dateRange string, tzOffsetMinutes int, includeStats bool) ([]db.JobWithDomain, int, error)
CreateScheduler(ctx context.Context, scheduler *db.Scheduler) error
GetScheduler(ctx context.Context, schedulerID string) (*db.Scheduler, error)
ListSchedulers(ctx context.Context, organisationID string) ([]*db.Scheduler, error)
UpdateScheduler(ctx context.Context, schedulerID string, updates *db.Scheduler, expectedIsEnabled *bool) error
DeleteScheduler(ctx context.Context, schedulerID string) error
GetSchedulersReadyToRun(ctx context.Context, limit int) ([]*db.Scheduler, error)
UpdateSchedulerNextRun(ctx context.Context, schedulerID string, nextRun time.Time) error
GetLastJobStartTimeForScheduler(ctx context.Context, schedulerID string) (*time.Time, error)
GetDomainNameByID(ctx context.Context, domainID int) (string, error)
GetDomainNames(ctx context.Context, domainIDs []int) (map[int]string, error)
ListUserOrganisations(userID string) ([]db.UserOrganisation, error)
ValidateOrganisationMembership(userID, organisationID string) (bool, error)
SetActiveOrganisation(userID, organisationID string) error
GetEffectiveOrganisationID(user *db.User) string
GetOrganisationMemberRole(ctx context.Context, userID, organisationID string) (string, error)
ListOrganisationMembers(ctx context.Context, organisationID string) ([]db.OrganisationMember, error)
IsOrganisationMemberEmail(ctx context.Context, organisationID, email string) (bool, error)
RemoveOrganisationMember(ctx context.Context, userID, organisationID string) error
UpdateOrganisationMemberRole(ctx context.Context, userID, organisationID, role string) error
CountOrganisationAdmins(ctx context.Context, organisationID string) (int, error)
CreateOrganisation(name string) (*db.Organisation, error)
CreateOrganisationForUser(userID, name string) (*db.Organisation, error)
AddOrganisationMember(userID, organisationID, role string) error
CreateOrganisationInvite(ctx context.Context, invite *db.OrganisationInvite) (*db.OrganisationInvite, error)
ListOrganisationInvites(ctx context.Context, organisationID string) ([]db.OrganisationInvite, error)
RevokeOrganisationInvite(ctx context.Context, inviteID, organisationID string) error
GetOrganisationInviteByToken(ctx context.Context, token string) (*db.OrganisationInvite, error)
AcceptOrganisationInvite(ctx context.Context, token, userID string) (*db.OrganisationInvite, error)
SetOrganisationPlan(ctx context.Context, organisationID, planID string) error
GetOrganisationPlanID(ctx context.Context, organisationID string) (string, error)
ListDailyUsage(ctx context.Context, organisationID string, startDate, endDate time.Time) ([]db.DailyUsageEntry, error)
CreateSlackConnection(ctx context.Context, conn *db.SlackConnection) error
GetSlackConnection(ctx context.Context, connectionID string) (*db.SlackConnection, error)
ListSlackConnections(ctx context.Context, organisationID string) ([]*db.SlackConnection, error)
DeleteSlackConnection(ctx context.Context, connectionID, organisationID string) error
CreateSlackUserLink(ctx context.Context, link *db.SlackUserLink) error
GetSlackUserLink(ctx context.Context, userID, connectionID string) (*db.SlackUserLink, error)
UpdateSlackUserLinkNotifications(ctx context.Context, userID, connectionID string, dmNotifications bool) error
DeleteSlackUserLink(ctx context.Context, userID, connectionID string) error
StoreSlackToken(ctx context.Context, connectionID, token string) error
GetSlackToken(ctx context.Context, connectionID string) (string, error)
ListNotifications(ctx context.Context, organisationID string, limit, offset int, unreadOnly bool) ([]*db.Notification, int, error)
GetUnreadNotificationCount(ctx context.Context, organisationID string) (int, error)
MarkNotificationRead(ctx context.Context, notificationID, organisationID string) error
MarkAllNotificationsRead(ctx context.Context, organisationID string) error
CreateWebflowConnection(ctx context.Context, conn *db.WebflowConnection) error
GetWebflowConnection(ctx context.Context, connectionID string) (*db.WebflowConnection, error)
ListWebflowConnections(ctx context.Context, organisationID string) ([]*db.WebflowConnection, error)
DeleteWebflowConnection(ctx context.Context, connectionID, organisationID string) error
StoreWebflowToken(ctx context.Context, connectionID, token string) error
GetWebflowToken(ctx context.Context, connectionID string) (string, error)
CreateGoogleConnection(ctx context.Context, conn *db.GoogleAnalyticsConnection) error
GetGoogleConnection(ctx context.Context, connectionID string) (*db.GoogleAnalyticsConnection, error)
ListGoogleConnections(ctx context.Context, organisationID string) ([]*db.GoogleAnalyticsConnection, error)
DeleteGoogleConnection(ctx context.Context, connectionID, organisationID string) error
UpdateGoogleConnectionStatus(ctx context.Context, connectionID, organisationID, status string) error
StoreGoogleToken(ctx context.Context, connectionID, refreshToken string) error
GetGoogleToken(ctx context.Context, connectionID string) (string, error)
GetActiveGAConnectionForOrganisation(ctx context.Context, orgID string) (*db.GoogleAnalyticsConnection, error)
GetActiveGAConnectionForDomain(ctx context.Context, organisationID string, domainID int) (*db.GoogleAnalyticsConnection, error)
GetDomainsForOrganisation(ctx context.Context, organisationID string) ([]db.OrganisationDomain, error)
UpdateConnectionLastSync(ctx context.Context, connectionID string) error
UpdateConnectionDomains(ctx context.Context, connectionID string, domainIDs []int) error
MarkConnectionInactive(ctx context.Context, connectionID, reason string) error
UpsertPageWithAnalytics(ctx context.Context, organisationID string, domainID int, path string, pageViews map[string]int64, connectionID string) (int, error)
CalculateTrafficScores(ctx context.Context, organisationID string, domainID int) error
ApplyTrafficScoresToTasks(ctx context.Context, organisationID string, domainID int) error
GetOrCreateDomainID(ctx context.Context, domain string) (int, error)
UpsertOrganisationDomain(ctx context.Context, organisationID string, domainID int) error
UpsertGA4Account(ctx context.Context, account *db.GoogleAnalyticsAccount) error
ListGA4Accounts(ctx context.Context, organisationID string) ([]*db.GoogleAnalyticsAccount, error)
GetGA4Account(ctx context.Context, accountID string) (*db.GoogleAnalyticsAccount, error)
GetGA4AccountByGoogleID(ctx context.Context, organisationID, googleAccountID string) (*db.GoogleAnalyticsAccount, error)
StoreGA4AccountToken(ctx context.Context, accountID, refreshToken string) error
GetGA4AccountToken(ctx context.Context, accountID string) (string, error)
GetGA4AccountWithToken(ctx context.Context, organisationID string) (*db.GoogleAnalyticsAccount, error)
GetGAConnectionWithToken(ctx context.Context, organisationID string) (*db.GoogleAnalyticsConnection, error)
UpsertPlatformOrgMapping(ctx context.Context, mapping *db.PlatformOrgMapping) error
GetPlatformOrgMapping(ctx context.Context, platform, platformID string) (*db.PlatformOrgMapping, error)
GetOrganisationUsageStats(ctx context.Context, orgID string) (*db.UsageStats, error)
GetActivePlans(ctx context.Context) ([]db.Plan, error)
CreateOrUpdateSiteSetting(ctx context.Context, setting *db.WebflowSiteSetting) error
GetSiteSetting(ctx context.Context, organisationID, webflowSiteID string) (*db.WebflowSiteSetting, error)
GetSiteSettingByID(ctx context.Context, id string) (*db.WebflowSiteSetting, error)
ListConfiguredSiteSettings(ctx context.Context, organisationID string) ([]*db.WebflowSiteSetting, error)
ListAllSiteSettings(ctx context.Context, organisationID string) ([]*db.WebflowSiteSetting, error)
ListSiteSettingsByConnection(ctx context.Context, connectionID string) ([]*db.WebflowSiteSetting, error)
UpdateSiteSchedule(ctx context.Context, organisationID, webflowSiteID string, scheduleIntervalHours *int, schedulerID string) error
UpdateSiteAutoPublish(ctx context.Context, organisationID, webflowSiteID string, enabled bool, webhookID string) error
DeleteSiteSetting(ctx context.Context, organisationID, webflowSiteID string) error
DeleteSiteSettingsByConnection(ctx context.Context, connectionID string) error
}
type DBInterfaceGA4 ¶
type DBInterfaceGA4 interface {
GetActiveGAConnectionForDomain(ctx context.Context, organisationID string, domainID int) (*db.GoogleAnalyticsConnection, error)
GetDomainNameByID(ctx context.Context, domainID int) (string, error)
GetGoogleToken(ctx context.Context, connectionID string) (string, error)
UpdateConnectionLastSync(ctx context.Context, connectionID string) error
MarkConnectionInactive(ctx context.Context, connectionID, reason string) error
UpsertPageWithAnalytics(ctx context.Context, organisationID string, domainID int, path string, pageViews map[string]int64, connectionID string) (int, error)
CalculateTrafficScores(ctx context.Context, organisationID string, domainID int) error
ApplyTrafficScoresToTasks(ctx context.Context, organisationID string, domainID int) error
}
DBInterfaceGA4 defines the database operations needed by the progressive fetcher
type DomainResponse ¶
DomainResponse represents a domain in API responses
type ErrorCode ¶
type ErrorCode string
const ( ErrCodeBadRequest ErrorCode = "BAD_REQUEST" ErrCodeForbidden ErrorCode = "FORBIDDEN" ErrCodeNotFound ErrorCode = "NOT_FOUND" ErrCodeMethodNotAllowed ErrorCode = "METHOD_NOT_ALLOWED" ErrCodeConflict ErrorCode = "CONFLICT" ErrCodeValidation ErrorCode = "VALIDATION_ERROR" ErrCodeRateLimit ErrorCode = "RATE_LIMIT_EXCEEDED" ErrCodeInternal ErrorCode = "INTERNAL_ERROR" ErrCodeDatabaseError ErrorCode = "DATABASE_ERROR" )
type ErrorResponse ¶
type ExportColumn ¶
ExportColumn describes a column in exported task datasets
type GA4APIError ¶
GA4APIError represents a non-200 response from the GA4 Data API.
func (*GA4APIError) Error ¶
func (err *GA4APIError) Error() string
func (*GA4APIError) IsUnauthorised ¶
func (err *GA4APIError) IsUnauthorised() bool
type GA4Account ¶
type GA4Account struct {
AccountID string `json:"account_id"`
DisplayName string `json:"display_name"`
}
GA4Account represents a Google Analytics account
type GA4AccountResponse ¶
type GA4AccountResponse struct {
ID string `json:"id"`
GoogleAccountID string `json:"google_account_id"`
GoogleAccountName string `json:"google_account_name,omitempty"`
GoogleEmail string `json:"google_email,omitempty"`
HasToken bool `json:"has_token"`
CreatedAt string `json:"created_at"`
}
GA4AccountResponse represents a Google Analytics account in API responses
type GA4Client ¶
type GA4Client struct {
// contains filtered or unexported fields
}
GA4Client is an HTTP client for the Google Analytics 4 Data API
func NewGA4Client ¶
NewGA4Client creates a new GA4 Data API client
func (*GA4Client) FetchTopPages ¶
func (c *GA4Client) FetchTopPages(ctx context.Context, propertyID string, limit, offset int, allowedHostnames []string) ([]PageViewData, error)
FetchTopPages fetches top N pages ordered by screenPageViews descending Returns page data for 7-day, 28-day, and 180-day lookback periods Makes 3 separate API calls and merges results by path
func (*GA4Client) FetchTopPagesWithRetry ¶
func (c *GA4Client) FetchTopPagesWithRetry(ctx context.Context, propertyID, refreshToken string, limit, offset int, allowedHostnames []string) ([]PageViewData, error)
FetchTopPagesWithRetry fetches top pages with automatic token refresh on 401
type GA4Property ¶
type GA4Property struct {
PropertyID string `json:"property_id"` // e.g., "123456789"
DisplayName string `json:"display_name"` // e.g., "My Website"
PropertyType string `json:"property_type"` // e.g., "PROPERTY_TYPE_ORDINARY"
}
GA4Property represents a Google Analytics 4 property
type GoogleConnectionResponse ¶
type GoogleConnectionResponse struct {
ID string `json:"id"`
GA4PropertyID string `json:"ga4_property_id,omitempty"`
GA4PropertyName string `json:"ga4_property_name,omitempty"`
GoogleAccountName string `json:"google_account_name,omitempty"`
GoogleEmail string `json:"google_email,omitempty"`
Status string `json:"status"`
DomainIDs pq.Int64Array `json:"domain_ids,omitempty"`
CreatedAt string `json:"created_at"`
}
GoogleConnectionResponse represents a Google Analytics connection in API responses
type GoogleTokenResponse ¶
type GoogleTokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
}
GoogleTokenResponse represents the response from Google's token endpoint
type GoogleUserInfo ¶
type GoogleUserInfo struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
}
GoogleUserInfo contains user info from Google
type Handler ¶
type Handler struct {
DB DBClient
JobsManager jobs.JobManagerInterface
Loops *loops.Client
Broker BrokerCleaner
GoogleClientID string
GoogleClientSecret string
}
func NewHandler ¶
func NewHandler(pgDB DBClient, jobsManager jobs.JobManagerInterface, loopsClient *loops.Client, broker BrokerCleaner, googleClientID, googleClientSecret string) *Handler
broker may be nil when Redis is not configured — admin reset endpoints skip the Redis clear in that case.
func (*Handler) AdminReclaimRedis ¶ added in v0.33.10
func (h *Handler) AdminReclaimRedis(w http.ResponseWriter, r *http.Request)
One-off backfill sweep for terminal-status jobs whose Redis keys were never cleaned. Idempotent; gated on ALLOW_DB_RESET.
func (*Handler) AdminResetData ¶
func (h *Handler) AdminResetData(w http.ResponseWriter, r *http.Request)
AdminResetData handles the admin data-only reset endpoint Clears all data but preserves schema - safe option for clearing test data
func (*Handler) AdminResetDatabase ¶
func (h *Handler) AdminResetDatabase(w http.ResponseWriter, r *http.Request)
Requires admin JWT and ALLOW_DB_RESET=true.
func (*Handler) AuthProfile ¶
func (h *Handler) AuthProfile(w http.ResponseWriter, r *http.Request)
AuthProfile handles GET/PATCH /v1/auth/profile
func (*Handler) AuthRegister ¶
func (h *Handler) AuthRegister(w http.ResponseWriter, r *http.Request)
AuthRegister handles POST /v1/auth/register
func (*Handler) AuthSession ¶
func (h *Handler) AuthSession(w http.ResponseWriter, r *http.Request)
AuthSession handles POST /v1/auth/session
func (*Handler) DashboardActivity ¶
func (h *Handler) DashboardActivity(w http.ResponseWriter, r *http.Request)
func (*Handler) DashboardExternalRedirects ¶
func (h *Handler) DashboardExternalRedirects(w http.ResponseWriter, r *http.Request)
func (*Handler) DashboardSlowPages ¶
func (h *Handler) DashboardSlowPages(w http.ResponseWriter, r *http.Request)
func (*Handler) DashboardStats ¶
func (h *Handler) DashboardStats(w http.ResponseWriter, r *http.Request)
func (*Handler) DatabaseHealthCheck ¶
func (h *Handler) DatabaseHealthCheck(w http.ResponseWriter, r *http.Request)
func (*Handler) DevAutoLogin ¶
func (h *Handler) DevAutoLogin(w http.ResponseWriter, r *http.Request)
DevAutoLogin signs in as dev@example.com server-side and injects the session into localStorage. Sidesteps the browser→Supabase call that sandboxed preview browsers can't make (they reach localhost:8847 but not 127.0.0.1:54321). 404 outside APP_ENV=development. Optional ?redirect=/path query parameter (same-origin only).
func (*Handler) DomainsHandler ¶
func (h *Handler) DomainsHandler(w http.ResponseWriter, r *http.Request)
DomainsHandler handles requests to /v1/domains
func (*Handler) GetAccountProperties ¶
func (h *Handler) GetAccountProperties(w http.ResponseWriter, r *http.Request, googleAccountID string)
GetAccountProperties fetches properties for a Google account using stored refresh token GET /v1/integrations/google/accounts/{googleAccountId}/properties
func (*Handler) GetActiveOrganisation ¶
Writes the error response and returns "" on failure.
func (*Handler) GetActiveOrganisationWithUser ¶
func (*Handler) GoogleConnectionHandler ¶
func (h *Handler) GoogleConnectionHandler(w http.ResponseWriter, r *http.Request)
GoogleConnectionHandler handles requests to /v1/integrations/google/:id
func (*Handler) GoogleConnectionsHandler ¶
func (h *Handler) GoogleConnectionsHandler(w http.ResponseWriter, r *http.Request)
GoogleConnectionsHandler handles requests to /v1/integrations/google
func (*Handler) HandleGoogleOAuthCallback ¶
func (h *Handler) HandleGoogleOAuthCallback(w http.ResponseWriter, r *http.Request)
HandleGoogleOAuthCallback processes the OAuth callback from Google After successful auth, it fetches the user's GA4 properties and returns them
func (*Handler) HandleWebflowOAuthCallback ¶
func (h *Handler) HandleWebflowOAuthCallback(w http.ResponseWriter, r *http.Request)
HandleWebflowOAuthCallback processes the OAuth callback from Webflow
func (*Handler) HealthCheck ¶
func (h *Handler) HealthCheck(w http.ResponseWriter, r *http.Request)
func (*Handler) InitiateGoogleOAuth ¶
func (h *Handler) InitiateGoogleOAuth(w http.ResponseWriter, r *http.Request)
InitiateGoogleOAuth starts the OAuth flow
func (*Handler) InitiateWebflowOAuth ¶
func (h *Handler) InitiateWebflowOAuth(w http.ResponseWriter, r *http.Request)
InitiateWebflowOAuth starts the OAuth flow
func (*Handler) JobHandler ¶
func (h *Handler) JobHandler(w http.ResponseWriter, r *http.Request)
JobHandler handles requests to /v1/jobs/:id
func (*Handler) JobsHandler ¶
func (h *Handler) JobsHandler(w http.ResponseWriter, r *http.Request)
JobsHandler handles requests to /v1/jobs
func (*Handler) ListGA4Accounts ¶
func (h *Handler) ListGA4Accounts(w http.ResponseWriter, r *http.Request)
ListGA4Accounts returns stored GA4 accounts from the database GET /v1/integrations/google/accounts
func (*Handler) MetadataHandler ¶
func (h *Handler) MetadataHandler(w http.ResponseWriter, r *http.Request)
MetadataHandler handles GET /v1/metadata/metrics
func (*Handler) NotificationHandler ¶
func (h *Handler) NotificationHandler(w http.ResponseWriter, r *http.Request)
NotificationHandler handles requests to /v1/notifications/{id}
func (*Handler) NotificationsHandler ¶
func (h *Handler) NotificationsHandler(w http.ResponseWriter, r *http.Request)
NotificationsHandler handles requests to /v1/notifications
func (*Handler) NotificationsReadAllHandler ¶
func (h *Handler) NotificationsReadAllHandler(w http.ResponseWriter, r *http.Request)
NotificationsReadAllHandler handles POST /v1/notifications/read-all
func (*Handler) OrganisationInviteAcceptHandler ¶
func (h *Handler) OrganisationInviteAcceptHandler(w http.ResponseWriter, r *http.Request)
OrganisationInviteAcceptHandler handles POST /v1/organisations/invites/accept
func (*Handler) OrganisationInviteHandler ¶
func (h *Handler) OrganisationInviteHandler(w http.ResponseWriter, r *http.Request)
OrganisationInviteHandler handles DELETE /v1/organisations/invites/:id
func (*Handler) OrganisationInvitePreviewHandler ¶
func (h *Handler) OrganisationInvitePreviewHandler(w http.ResponseWriter, r *http.Request)
OrganisationInvitePreviewHandler handles GET /v1/organisations/invites/preview?token=... It is intentionally public so invite recipients can see who invited them before authentication.
func (*Handler) OrganisationInvitesHandler ¶
func (h *Handler) OrganisationInvitesHandler(w http.ResponseWriter, r *http.Request)
OrganisationInvitesHandler handles GET/POST /v1/organisations/invites
func (*Handler) OrganisationMemberHandler ¶
func (h *Handler) OrganisationMemberHandler(w http.ResponseWriter, r *http.Request)
OrganisationMemberHandler handles PATCH/DELETE /v1/organisations/members/:id
func (*Handler) OrganisationMembersHandler ¶
func (h *Handler) OrganisationMembersHandler(w http.ResponseWriter, r *http.Request)
OrganisationMembersHandler handles GET /v1/organisations/members
func (*Handler) OrganisationPlanHandler ¶
func (h *Handler) OrganisationPlanHandler(w http.ResponseWriter, r *http.Request)
OrganisationPlanHandler handles PUT /v1/organisations/plan
func (*Handler) OrganisationsHandler ¶
func (h *Handler) OrganisationsHandler(w http.ResponseWriter, r *http.Request)
OrganisationsHandler handles GET and POST /v1/organisations
func (*Handler) PlansHandler ¶
func (h *Handler) PlansHandler(w http.ResponseWriter, r *http.Request)
PlansHandler handles GET /v1/plans Returns available subscription plans (public endpoint for pricing page)
func (*Handler) RefreshGA4Accounts ¶
func (h *Handler) RefreshGA4Accounts(w http.ResponseWriter, r *http.Request)
RefreshGA4Accounts syncs accounts from Google API and updates the database POST /v1/integrations/google/accounts/refresh
func (*Handler) SaveGA4AccountProperties ¶
func (h *Handler) SaveGA4AccountProperties(w http.ResponseWriter, r *http.Request, googleAccountID string)
SaveGA4AccountProperties saves all properties for a stored GA4 account as inactive POST /v1/integrations/google/accounts/{googleAccountId}/save-properties
func (*Handler) SaveGoogleProperties ¶
func (h *Handler) SaveGoogleProperties(w http.ResponseWriter, r *http.Request)
SaveGoogleProperties saves all properties from a session, with specified ones marked as active
func (*Handler) SaveGoogleProperty ¶
func (h *Handler) SaveGoogleProperty(w http.ResponseWriter, r *http.Request)
SaveGoogleProperty saves the selected GA4 property
func (*Handler) SchedulerHandler ¶
func (h *Handler) SchedulerHandler(w http.ResponseWriter, r *http.Request)
SchedulerHandler handles requests to /v1/schedulers/:id
func (*Handler) SchedulersHandler ¶
func (h *Handler) SchedulersHandler(w http.ResponseWriter, r *http.Request)
SchedulersHandler handles requests to /v1/schedulers
func (*Handler) ServeAuthCallback ¶
func (h *Handler) ServeAuthCallback(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeAuthModal ¶
func (h *Handler) ServeAuthModal(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeConfigJS ¶
func (h *Handler) ServeConfigJS(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeDashboard ¶
func (h *Handler) ServeDashboard(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeDebugAuth ¶
func (h *Handler) ServeDebugAuth(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeExtensionAuth ¶
func (h *Handler) ServeExtensionAuth(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeHomepage ¶
func (h *Handler) ServeHomepage(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeInviteWelcome ¶
func (h *Handler) ServeInviteWelcome(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeJobDetails ¶
func (h *Handler) ServeJobDetails(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeNewDashboard ¶
func (h *Handler) ServeNewDashboard(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeSettings ¶
func (h *Handler) ServeSettings(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeSharedJobPage ¶
func (h *Handler) ServeSharedJobPage(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeTestComponents ¶
func (h *Handler) ServeTestComponents(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeTestDataComponents ¶
func (h *Handler) ServeTestDataComponents(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeTestLogin ¶
func (h *Handler) ServeTestLogin(w http.ResponseWriter, r *http.Request)
func (*Handler) ServeWelcome ¶
func (h *Handler) ServeWelcome(w http.ResponseWriter, r *http.Request)
func (*Handler) SetupRoutes ¶
func (*Handler) SharedJobHandler ¶
func (h *Handler) SharedJobHandler(w http.ResponseWriter, r *http.Request)
func (*Handler) SlackConnectionHandler ¶
func (h *Handler) SlackConnectionHandler(w http.ResponseWriter, r *http.Request)
SlackConnectionHandler handles requests to /v1/integrations/slack/:id and sub-routes
func (*Handler) SlackConnectionsHandler ¶
func (h *Handler) SlackConnectionsHandler(w http.ResponseWriter, r *http.Request)
SlackConnectionsHandler handles requests to /v1/integrations/slack
func (*Handler) SlackOAuthCallback ¶
func (h *Handler) SlackOAuthCallback(w http.ResponseWriter, r *http.Request)
SlackOAuthCallback handles the OAuth callback (no auth middleware)
func (*Handler) SwitchOrganisationHandler ¶
func (h *Handler) SwitchOrganisationHandler(w http.ResponseWriter, r *http.Request)
SwitchOrganisationHandler handles POST /v1/organisations/switch
func (*Handler) UpdateGoogleConnection ¶
func (h *Handler) UpdateGoogleConnection(w http.ResponseWriter, r *http.Request, connectionID string)
UpdateGoogleConnection updates domain mappings for an existing connection PATCH /v1/integrations/google/{id}
func (*Handler) UpdateGooglePropertyStatus ¶
func (h *Handler) UpdateGooglePropertyStatus(w http.ResponseWriter, r *http.Request, connectionID string)
UpdateGooglePropertyStatus updates the status of a Google Analytics connection
func (*Handler) UsageHandler ¶
func (h *Handler) UsageHandler(w http.ResponseWriter, r *http.Request)
UsageHandler handles GET /v1/usage Returns current usage statistics for the user's active organisation
func (*Handler) UsageHistoryHandler ¶
func (h *Handler) UsageHistoryHandler(w http.ResponseWriter, r *http.Request)
UsageHistoryHandler handles GET /v1/usage/history
func (*Handler) WebflowConnectionHandler ¶
func (h *Handler) WebflowConnectionHandler(w http.ResponseWriter, r *http.Request)
WebflowConnectionHandler handles requests to /v1/integrations/webflow/:id
func (*Handler) WebflowConnectionsHandler ¶
func (h *Handler) WebflowConnectionsHandler(w http.ResponseWriter, r *http.Request)
WebflowConnectionsHandler handles requests to /v1/integrations/webflow
func (*Handler) WebflowSitesHandler ¶
func (h *Handler) WebflowSitesHandler(w http.ResponseWriter, r *http.Request)
WebflowSitesHandler handles requests to /v1/integrations/webflow/{connection_id}/sites
func (*Handler) WebflowWebhook ¶
func (h *Handler) WebflowWebhook(w http.ResponseWriter, r *http.Request)
type HealthResponse ¶
type HealthResponse struct {
Status string `json:"status"`
Timestamp string `json:"timestamp"`
Service string `json:"service"`
Version string `json:"version,omitempty"`
}
HealthResponse represents a health check response
type JobActionRequest ¶
type JobActionRequest struct {
Action string `json:"action"`
}
JobActionRequest represents actions that can be performed on jobs
type JobResponse ¶
type JobResponse struct {
ID string `json:"id"`
DomainID int `json:"domain_id"`
Domain string `json:"domain"`
Status string `json:"status"`
TotalTasks int `json:"total_tasks"`
CompletedTasks int `json:"completed_tasks"`
FailedTasks int `json:"failed_tasks"`
SkippedTasks int `json:"skipped_tasks"`
Progress float64 `json:"progress"`
CreatedAt string `json:"created_at"`
StartedAt *string `json:"started_at,omitempty"`
CompletedAt *string `json:"completed_at,omitempty"`
// Additional fields for dashboard
DurationSeconds *int `json:"duration_seconds,omitempty"`
AvgTimePerTaskSeconds *float64 `json:"avg_time_per_task_seconds,omitempty"`
Stats map[string]any `json:"stats,omitempty"`
SchedulerID *string `json:"scheduler_id,omitempty"`
// Job configuration fields
Concurrency int `json:"concurrency"`
MaxPages int `json:"max_pages"`
SourceType *string `json:"source_type,omitempty"`
CrawlDelaySeconds *int `json:"crawl_delay_seconds,omitempty"`
AdaptiveDelaySeconds int `json:"adaptive_delay_seconds"`
}
JobResponse represents a job in API responses
type MetricInfo ¶
type MetricInfo struct {
Name string `json:"name"`
Description string `json:"description"`
InfoHTML string `json:"info_html"`
}
MetricInfo represents metadata about a metric
type NotificationResponse ¶
type NotificationResponse struct {
ID string `json:"id"`
Type string `json:"type"`
Subject string `json:"subject"`
Preview string `json:"preview"`
Message string `json:"message,omitempty"`
Link string `json:"link,omitempty"`
ReadAt *time.Time `json:"read_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
NotificationResponse is the JSON response for a notification
type NotificationsListResponse ¶
type NotificationsListResponse struct {
Notifications []NotificationResponse `json:"notifications"`
Total int `json:"total"`
UnreadCount int `json:"unread_count"`
}
NotificationsListResponse is the JSON response for listing notifications
type OAuthState ¶
type OAuthState struct {
UserID string `json:"u"`
OrgID string `json:"o"`
Timestamp int64 `json:"t"`
Nonce string `json:"n"`
}
OAuthState contains signed state data for CSRF protection Shared between Slack and Webflow
type OrganisationResponse ¶
type OrganisationResponse struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
OrganisationResponse represents an organisation in API responses
type PageViewData ¶
type PageViewData struct {
HostName string
PagePath string
PageViews7d int64
PageViews28d int64
PageViews180d int64
}
PageViewData represents analytics data for a single page
type PendingGASession ¶
type PendingGASession struct {
Accounts []GA4Account // Accounts fetched during OAuth
Properties []GA4Property // Properties fetched when account selected (optional, for backwards compat)
RefreshToken string
AccessToken string
State string
UserID string
Email string
OrgID string // Organisation ID from OAuth state
ExpiresAt time.Time
}
PendingGASession stores OAuth data temporarily until user completes account/property selection
type ProgressiveFetcher ¶
type ProgressiveFetcher struct {
// contains filtered or unexported fields
}
ProgressiveFetcher orchestrates GA4 data fetching in multiple phases
func NewProgressiveFetcher ¶
func NewProgressiveFetcher(database DBInterfaceGA4, clientID, clientSecret string) *ProgressiveFetcher
NewProgressiveFetcher creates a new progressive fetcher instance
func (*ProgressiveFetcher) FetchAndUpdatePages ¶
func (pf *ProgressiveFetcher) FetchAndUpdatePages(ctx context.Context, organisationID string, domainID int) error
FetchAndUpdatePages fetches GA4 data in 3 phases and updates the pages table Phase 1 is blocking (top 100 pages), phases 2-3 run in background goroutines
type PublicPlan ¶
type PublicPlan struct {
ID string `json:"id"`
Name string `json:"name"`
DisplayName string `json:"display_name"`
DailyPageLimit int `json:"daily_page_limit"`
MonthlyPriceCents int `json:"monthly_price_cents"`
}
PublicPlan is a DTO for the public /v1/plans endpoint Excludes internal metadata fields (is_active, sort_order, created_at)
type SchedulerRequest ¶
type SchedulerRequest struct {
Domain string `json:"domain"` // Only used for creation, not update
ScheduleIntervalHours *int `json:"schedule_interval_hours,omitempty"` // Pointer for explicit optional updates
Concurrency *int `json:"concurrency,omitempty"`
FindLinks *bool `json:"find_links,omitempty"`
MaxPages *int `json:"max_pages,omitempty"`
IncludePaths []string `json:"include_paths,omitempty"`
ExcludePaths []string `json:"exclude_paths,omitempty"`
IsEnabled *bool `json:"is_enabled,omitempty"`
ExpectedIsEnabled *bool `json:"expected_is_enabled,omitempty"` // Optional optimistic concurrency hint
}
SchedulerRequest represents the request body for creating/updating a scheduler
type SchedulerResponse ¶
type SchedulerResponse struct {
ID string `json:"id"`
Domain string `json:"domain"`
ScheduleIntervalHours int `json:"schedule_interval_hours"`
NextRunAt string `json:"next_run_at"`
IsEnabled bool `json:"is_enabled"`
Concurrency int `json:"concurrency"`
FindLinks bool `json:"find_links"`
MaxPages int `json:"max_pages"`
IncludePaths []string `json:"include_paths,omitempty"`
ExcludePaths []string `json:"exclude_paths,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
SchedulerResponse represents a scheduler in API responses
type SlackConnectRequest ¶
type SlackConnectRequest struct {
RedirectURI string `json:"redirect_uri,omitempty"`
}
SlackConnectRequest represents the request to initiate OAuth
type SlackConnectResponse ¶
type SlackConnectResponse struct {
AuthURL string `json:"auth_url"`
}
SlackConnectResponse returns the OAuth URL to redirect to
type SlackConnectionResponse ¶
type SlackConnectionResponse struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
WorkspaceName string `json:"workspace_name"`
CreatedAt string `json:"created_at"`
}
SlackConnectionResponse represents a Slack connection in API responses
type SlackLinkUserRequest ¶
type SlackLinkUserRequest struct {
ConnectionID string `json:"connection_id"`
SlackUserID string `json:"slack_user_id,omitempty"` // Optional if using email match
DMNotifications bool `json:"dm_notifications"`
}
SlackLinkUserRequest represents the request to link a Slack user
type SlackUpdateNotificationsRequest ¶
type SlackUpdateNotificationsRequest struct {
DMNotifications bool `json:"dm_notifications"`
}
SlackUpdateNotificationsRequest updates notification preferences
type SlackUserLinkResponse ¶
type SlackUserLinkResponse struct {
ID string `json:"id"`
SlackUserID string `json:"slack_user_id"`
DMNotifications bool `json:"dm_notifications"`
CreatedAt string `json:"created_at"`
}
SlackUserLinkResponse represents a user link in API responses
type SuccessResponse ¶
type SuccessResponse struct {
Status string `json:"status"`
Data any `json:"data,omitempty"`
Message string `json:"message,omitempty"`
RequestID string `json:"request_id,omitempty"`
}
SuccessResponse represents a standardised success response
type SwitchOrganisationRequest ¶
type SwitchOrganisationRequest struct {
OrganisationID string `json:"organisation_id"`
}
SwitchOrganisationRequest represents the request to switch active organisation
type TaskQueryBuilder ¶
TaskQueryBuilder holds the SQL queries and arguments for task retrieval
type TaskQueryParams ¶
type TaskQueryParams struct {
Limit int
Offset int
Status string
CacheFilter string
PathFilter string
PerformanceFilter string // "slow" (>1500ms) or "very_slow" (>4000ms)
OrderBy string
}
TaskQueryParams holds parameters for task listing queries
type TaskResponse ¶
type TaskResponse struct {
ID string `json:"id"`
JobID string `json:"job_id"`
Host *string `json:"host,omitempty"`
Path string `json:"path"`
URL string `json:"url"`
Status string `json:"status"`
StatusCode *int `json:"status_code,omitempty"`
ResponseTime *int `json:"response_time,omitempty"`
CacheStatus *string `json:"cache_status,omitempty"`
SecondResponseTime *int `json:"second_response_time,omitempty"`
SecondCacheStatus *string `json:"second_cache_status,omitempty"`
ContentType *string `json:"content_type,omitempty"`
Error *string `json:"error,omitempty"`
SourceType *string `json:"source_type,omitempty"`
SourceURL *string `json:"source_url,omitempty"`
CreatedAt string `json:"created_at"`
StartedAt *string `json:"started_at,omitempty"`
CompletedAt *string `json:"completed_at,omitempty"`
RetryCount int `json:"retry_count"`
PageViews7d *int `json:"page_views_7d,omitempty"`
PageViews28d *int `json:"page_views_28d,omitempty"`
PageViews180d *int `json:"page_views_180d,omitempty"`
}
TaskResponse represents a task in API responses
type UpdateAutoPublishRequest ¶
type UpdateAutoPublishRequest struct {
ConnectionID string `json:"connection_id"`
Enabled bool `json:"enabled"`
}
UpdateAutoPublishRequest represents the request body for toggling auto-publish
type UpdateOrganisationMemberRoleRequest ¶
type UpdateOrganisationMemberRoleRequest struct {
Role string `json:"role"`
}
type UpdateScheduleRequest ¶
type UpdateScheduleRequest struct {
ConnectionID string `json:"connection_id"`
ScheduleIntervalHours *int `json:"schedule_interval_hours"` // nil to remove schedule
}
UpdateScheduleRequest represents the request body for updating a site's schedule
type UserResponse ¶
type UserResponse struct {
ID string `json:"id"`
Email string `json:"email"`
FirstName *string `json:"first_name"`
LastName *string `json:"last_name"`
FullName *string `json:"full_name"`
OrganisationID *string `json:"organisation_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
UserResponse represents a user in API responses
type WebflowAuthInfo ¶
type WebflowAuthInfo struct {
UserID string
WorkspaceIDs []string
// User info from authorized_by endpoint
UserEmail string
UserFirstName string
UserLastName string
DisplayName string // Combined name for display (e.g., "Simon Chua" or email)
}
WebflowAuthInfo contains user and workspace info from Webflow's API
type WebflowConnectionResponse ¶
type WebflowConnectionResponse struct {
ID string `json:"id"`
WebflowWorkspaceID string `json:"webflow_workspace_id,omitempty"`
WorkspaceName string `json:"workspace_name,omitempty"`
CreatedAt string `json:"created_at"`
}
WebflowConnectionResponse represents a Webflow connection in API responses
type WebflowCustomDomain ¶
type WebflowCustomDomain struct {
ID string `json:"id"`
URL string `json:"url"`
LastPublished *string `json:"lastPublished,omitempty"`
}
WebflowCustomDomain represents a custom domain from the Webflow API v2
type WebflowSite ¶
type WebflowSite struct {
ID string `json:"id"`
WorkspaceID string `json:"workspaceId,omitempty"`
DisplayName string `json:"displayName"`
ShortName string `json:"shortName"`
LastPublished string `json:"lastPublished,omitempty"`
LastUpdated string `json:"lastUpdated,omitempty"`
CustomDomains []WebflowCustomDomain `json:"customDomains,omitempty"`
}
WebflowSite represents a site from the Webflow API v2
type WebflowSiteSettingResponse ¶
type WebflowSiteSettingResponse struct {
WebflowSiteID string `json:"webflow_site_id"`
SiteName string `json:"site_name"`
PrimaryDomain string `json:"primary_domain"`
LastPublished string `json:"last_published,omitempty"`
ScheduleIntervalHours *int `json:"schedule_interval_hours"`
AutoPublishEnabled bool `json:"auto_publish_enabled"`
SchedulerID *string `json:"scheduler_id,omitempty"`
}
WebflowSiteSettingResponse represents a site with its local settings
type WebflowSitesListResponse ¶
type WebflowSitesListResponse struct {
Sites []WebflowSiteSettingResponse `json:"sites"`
Pagination struct {
Total int `json:"total"`
Page int `json:"page"`
Limit int `json:"limit"`
HasNext bool `json:"has_next"`
} `json:"pagination"`
}
WebflowSitesListResponse represents the paginated sites list response
type WebflowSitesResponse ¶
type WebflowSitesResponse struct {
Sites []WebflowSite `json:"sites"`
}
WebflowSitesResponse represents the response from Webflow's list sites API
type WebflowTokenResponse ¶
type WebflowTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
}
WebflowTokenResponse represents the response from Webflow's token endpoint
type WebflowUserInfo ¶
type WebflowUserInfo struct {
ID string
Email string
FirstName string
LastName string
DisplayName string
}
WebflowUserInfo contains user details from the authorized_by endpoint