diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordPage.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordPage.tsx
index e0b574ee2..225320368 100644
--- a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordPage.tsx
+++ b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordPage.tsx
@@ -147,7 +147,7 @@ export default function CookieBannerConsentRecordPage({
-
+
{record.userAgent ?? "-"}
diff --git a/pkg/cmd/consent-record/list/list.go b/pkg/cmd/consent-record/list/list.go
index eb490d856..b68e4770c 100644
--- a/pkg/cmd/consent-record/list/list.go
+++ b/pkg/cmd/consent-record/list/list.go
@@ -52,13 +52,13 @@ query($id: ID!, $first: Int, $after: CursorKey, $filter: CookieConsentRecordFilt
`
type consentRecord struct {
- ID string `json:"id"`
- VisitorID string `json:"visitorId"`
- Action string `json:"action"`
- SDKVersion string `json:"sdkVersion"`
- Regulation string `json:"regulation"`
- CountryCode string `json:"countryCode"`
- CreatedAt string `json:"createdAt"`
+ ID string `json:"id"`
+ VisitorID string `json:"visitorId"`
+ Action string `json:"action"`
+ SDKVersion string `json:"sdkVersion"`
+ Regulation *string `json:"regulation"`
+ CountryCode *string `json:"countryCode"`
+ CreatedAt string `json:"createdAt"`
}
func NewCmdList(f *cmdutil.Factory) *cobra.Command {
@@ -154,7 +154,15 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
rows := make([][]string, 0, len(records))
for _, r := range records {
- rows = append(rows, []string{r.ID, r.VisitorID, r.Action, r.SDKVersion, r.Regulation, r.CountryCode, r.CreatedAt})
+ regulation := "-"
+ if r.Regulation != nil {
+ regulation = *r.Regulation
+ }
+ countryCode := "-"
+ if r.CountryCode != nil {
+ countryCode = *r.CountryCode
+ }
+ rows = append(rows, []string{r.ID, r.VisitorID, r.Action, r.SDKVersion, regulation, countryCode, r.CreatedAt})
}
t := cmdutil.NewTable("ID", "VISITOR ID", "ACTION", "SDK VERSION", "REGULATION", "COUNTRY", "CREATED AT").Rows(rows...)
diff --git a/pkg/cmd/consent-record/view/view.go b/pkg/cmd/consent-record/view/view.go
index 2b24b0622..79bba9704 100644
--- a/pkg/cmd/consent-record/view/view.go
+++ b/pkg/cmd/consent-record/view/view.go
@@ -54,8 +54,8 @@ type viewResponse struct {
ConsentData string `json:"consentData"`
Action string `json:"action"`
SdkVersion string `json:"sdkVersion"`
- Regulation string `json:"regulation"`
- CountryCode string `json:"countryCode"`
+ Regulation *string `json:"regulation"`
+ CountryCode *string `json:"countryCode"`
CreatedAt string `json:"createdAt"`
} `json:"node"`
}
@@ -119,8 +119,12 @@ func NewCmdView(f *cmdutil.Factory) *cobra.Command {
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Visitor ID:"), v.VisitorID)
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Action:"), v.Action)
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("SDK Version:"), v.SdkVersion)
- _, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Regulation:"), v.Regulation)
- _, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Country Code:"), v.CountryCode)
+ if v.Regulation != nil {
+ _, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Regulation:"), *v.Regulation)
+ }
+ if v.CountryCode != nil {
+ _, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Country Code:"), *v.CountryCode)
+ }
if v.IPAddress != nil && *v.IPAddress != "" {
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("IP Address:"), *v.IPAddress)
}
diff --git a/pkg/cookiebanner/service.go b/pkg/cookiebanner/service.go
index 8b11ef51a..e58de21ac 100644
--- a/pkg/cookiebanner/service.go
+++ b/pkg/cookiebanner/service.go
@@ -103,8 +103,8 @@ type (
ConsentData json.RawMessage
Action coredata.CookieConsentAction
SdkVersion string
- Regulation Regulation
- CountryCode coredata.CountryCode
+ Regulation *Regulation
+ CountryCode *coredata.CountryCode
}
DetectedCookie struct {
@@ -1847,6 +1847,10 @@ func (s *Service) RecordConsent(
CreatedAt: time.Now(),
}
+ if record.Regulation != nil && *record.Regulation == coredata.RegulationNone {
+ record.Regulation = nil
+ }
+
if err := record.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert consent record: %w", err)
}
diff --git a/pkg/coredata/cookie_consent_record.go b/pkg/coredata/cookie_consent_record.go
index a3b74f58b..a1bc61591 100644
--- a/pkg/coredata/cookie_consent_record.go
+++ b/pkg/coredata/cookie_consent_record.go
@@ -40,8 +40,8 @@ type (
ConsentData json.RawMessage `db:"consent_data"`
Action CookieConsentAction `db:"action"`
SdkVersion string `db:"sdk_version"`
- Regulation Regulation `db:"regulation"`
- CountryCode CountryCode `db:"country_code"`
+ Regulation *Regulation `db:"regulation"`
+ CountryCode *CountryCode `db:"country_code"`
CreatedAt time.Time `db:"created_at"`
}
diff --git a/pkg/coredata/migrations/20260507T143000Z.sql b/pkg/coredata/migrations/20260507T143000Z.sql
new file mode 100644
index 000000000..204a00514
--- /dev/null
+++ b/pkg/coredata/migrations/20260507T143000Z.sql
@@ -0,0 +1,22 @@
+-- Copyright (c) 2026 Probo Inc .
+--
+-- Permission to use, copy, modify, and/or distribute this software for any
+-- purpose with or without fee is hereby granted, provided that the above
+-- copyright notice and this permission notice appear in all copies.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+-- PERFORMANCE OF THIS SOFTWARE.
+
+ALTER TABLE cookie_consent_records
+ ALTER COLUMN regulation DROP NOT NULL;
+
+ALTER TABLE cookie_consent_records
+ ALTER COLUMN country_code DROP NOT NULL;
+
+UPDATE cookie_consent_records SET regulation = NULL WHERE regulation = '';
+UPDATE cookie_consent_records SET country_code = NULL WHERE country_code = '';
diff --git a/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql b/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql
index 6b82bdd2f..39bbd42f7 100644
--- a/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql
+++ b/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql
@@ -130,8 +130,8 @@ type CookieConsentRecord implements Node {
consentData: String!
action: CookieConsentAction!
sdkVersion: String!
- regulation: Regulation!
- countryCode: CountryCode!
+ regulation: Regulation
+ countryCode: CountryCode
createdAt: Datetime!
}
diff --git a/pkg/server/api/cookiebanner/v1/handler.go b/pkg/server/api/cookiebanner/v1/handler.go
index fac8b3086..b4b5314f3 100644
--- a/pkg/server/api/cookiebanner/v1/handler.go
+++ b/pkg/server/api/cookiebanner/v1/handler.go
@@ -72,7 +72,11 @@ func (h *Handler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
lang := r.URL.Query().Get("lang")
cc := h.resolveCountryCode(r)
- regulation := cookiebanner.RegulationForCountry(cc)
+
+ var regulation cookiebanner.Regulation
+ if cc != nil {
+ regulation = cookiebanner.RegulationForCountry(*cc)
+ }
config, err := h.cookieBannerSvc.GetActiveBannerConfig(r.Context(), bannerID, lang, regulation)
if err != nil {
@@ -92,16 +96,16 @@ func (h *Handler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
httpserver.RenderJSON(w, http.StatusOK, config)
}
-func (h *Handler) resolveCountryCode(r *http.Request) coredata.CountryCode {
+func (h *Handler) resolveCountryCode(r *http.Request) *coredata.CountryCode {
ip := clientip.Extract(r)
cc, err := h.geolocSvc.LookupCountry(r.Context(), ip)
if err != nil {
h.logger.ErrorCtx(r.Context(), "cannot resolve country for IP", log.Error(err))
- return ""
+ return nil
}
- return cc
+ return &cc
}
func (h *Handler) handleGetConsent(w http.ResponseWriter, r *http.Request) {
@@ -169,6 +173,12 @@ func (h *Handler) handlePostConsent(w http.ResponseWriter, r *http.Request) {
sdkVersion := r.Header.Get("X-SDK-Version")
cc := h.resolveCountryCode(r)
+ var regulation *cookiebanner.Regulation
+ if cc != nil {
+ r := cookiebanner.RegulationForCountry(*cc)
+ regulation = &r
+ }
+
req := cookiebanner.RecordConsentRequest{
Version: body.Version,
VisitorID: body.VisitorID,
@@ -177,7 +187,7 @@ func (h *Handler) handlePostConsent(w http.ResponseWriter, r *http.Request) {
ConsentData: body.ConsentData,
Action: body.Action,
SdkVersion: sdkVersion,
- Regulation: cookiebanner.RegulationForCountry(cc),
+ Regulation: regulation,
CountryCode: cc,
}
diff --git a/pkg/server/api/mcp/v1/specification.yaml b/pkg/server/api/mcp/v1/specification.yaml
index 8419874b6..b1b7220e9 100644
--- a/pkg/server/api/mcp/v1/specification.yaml
+++ b/pkg/server/api/mcp/v1/specification.yaml
@@ -9565,8 +9565,6 @@ components:
- consent_data
- action
- sdk_version
- - regulation
- - country_code
- created_at
properties:
id:
@@ -9604,9 +9602,11 @@ components:
regulation:
$ref: "#/components/schemas/Regulation"
description: Applicable regulation
+ nullable: true
country_code:
$ref: "#/components/schemas/CountryCode"
description: Visitor country code (ISO 3166-1 alpha-2)
+ nullable: true
created_at:
type: string
format: date-time