@scalemule/news-publication 0.0.46 → 0.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -237,3 +237,11 @@ Moderate through **Newsroom → Community Maps → Comments**. Approval requires
237
237
  explicit guideline review and the current revision. Existing pumpkin reactions
238
238
  remain configurable alongside voting. The UI links to `/account?next=...`; the
239
239
  publication must validate that return path and preserve it through sign-in.
240
+
241
+ ### Community partnerships
242
+
243
+ `SPONSORSHIP_OFFERINGS` defines preliminary USD rates and exact web/email deliverables. `Placement`, `SponsorParty`, `Campaign` and `SponsorshipReport` describe the publication-owned Blog API. `SponsorAcknowledgment` from `@scalemule/news-publication/sponsorship-view` and `sponsorship.css` use publication tokens, explicit labels and safe HTTPS links. They do not insert article ads, load advertising scripts, or measure preview renders.
244
+
245
+ Inventory is unavailable until a verified operational placement is active. `placementAvailable` enforces verification freshness and keeps paid briefings disabled. Campaign approval, authorization, allocation capacity and manual commercial references remain server responsibilities. Report HTML distinguishes observed counts from unavailable data and can be printed or rendered to PDF. No invoice or payment is initiated by this SDK.
246
+
247
+ The consent banner now offers a choice in every geography where optional measurement requires one. `measurementConsent` is the server gate for current, explicitly allowed categories and GPC/DNT. Positive permission is local: unsigned URL parameters and a binary network hub cannot grant all categories. Rendering sponsorship recognition does not require tracking consent; measuring it requires both performance and advertising permission.
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { setupNetworkConsentDelegation, COOKIE_CONSENT_EVENT, listedPublications, decorateNetworkUrl } from './chunk-UTBV6JJX.js';
2
+ import { setupNetworkConsentDelegation, COOKIE_CONSENT_EVENT, listedPublications, decorateNetworkUrl } from './chunk-JV76ZEIA.js';
3
3
  import { useState, useId, useRef, useEffect } from 'react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -0,0 +1,65 @@
1
+ // src/sponsorships.ts
2
+ var SPONSORSHIP_POLICY = "Sponsors receive clearly identified recognition. Sponsorship does not influence reporting, event selection, factual information, rankings or editorial recommendations.";
3
+ var SPONSORSHIP_OFFERINGS = [
4
+ {
5
+ type: "community_partner",
6
+ name: "Publication Community Partner",
7
+ price_cents: 35e3,
8
+ duration: "One calendar month; exact start and end dates in the agreement.",
9
+ deliverables: "One acknowledgment on the publication's community partners page and one compact acknowledgment below the community calendar. No article placements.",
10
+ acknowledgments: "Two defined web locations; recurring display during the campaign, subject to reader repetition limits.",
11
+ creative: "Name, approved logo, up to 140 characters of copy and one HTTPS link.",
12
+ max_sponsors: 2,
13
+ product_path: "/community-partners"
14
+ },
15
+ {
16
+ type: "community_calendar",
17
+ name: "Community Calendar Sponsor",
18
+ price_cents: 25e3,
19
+ duration: "One calendar month; exact start and end dates in the agreement.",
20
+ deliverables: "One acknowledgment above the independently curated community events calendar.",
21
+ acknowledgments: "One web location; recurring display during the campaign, subject to reader repetition limits.",
22
+ creative: "Name, approved logo, up to 140 characters of copy and one HTTPS link.",
23
+ max_sponsors: 1,
24
+ product_path: "/this-week"
25
+ },
26
+ {
27
+ type: "daily_briefing",
28
+ name: "Daily Briefing Sponsor",
29
+ price_cents: 3e4,
30
+ duration: "One calendar month after verified newsletter delivery is operational.",
31
+ deliverables: "One acknowledgment per agreed briefing edition. Edition dates and count must be specified in the agreement before booking.",
32
+ acknowledgments: "One per contracted edition; no minimum send count is promised before launch.",
33
+ creative: "Name, optional logo, up to 140 characters of approved copy and one HTTPS link.",
34
+ max_sponsors: 1,
35
+ product_path: "/newsletter"
36
+ },
37
+ {
38
+ type: "community_guide",
39
+ name: "Community Guide Sponsor",
40
+ price_cents: null,
41
+ duration: "Fixed dates agreed for a named guide.",
42
+ deliverables: "One acknowledgment on one named, independently edited community guide; scope and updates agreed in writing.",
43
+ acknowledgments: "One web location per contracted guide.",
44
+ creative: "Name, approved logo, up to 140 characters of copy and one HTTPS link.",
45
+ max_sponsors: 1,
46
+ product_path: "/guides"
47
+ }
48
+ ];
49
+ function safeSponsorUrl(value) {
50
+ if (typeof value !== "string" || value.length > 2048) return void 0;
51
+ try {
52
+ const url = new URL(value);
53
+ if (url.protocol !== "https:" || url.username || url.password)
54
+ return void 0;
55
+ return url.toString();
56
+ } catch {
57
+ return void 0;
58
+ }
59
+ }
60
+ function placementAvailable(placement, now = Date.now()) {
61
+ const verified = placement.verified_at && Date.parse(placement.verified_at);
62
+ return placement.placement_type !== "daily_briefing" && placement.active && placement.availability === "available" && Boolean(safeSponsorUrl(placement.verification_url)) && typeof verified === "number" && Number.isFinite(verified) && verified <= now && now - verified <= 90 * 864e5;
63
+ }
64
+
65
+ export { SPONSORSHIP_OFFERINGS, SPONSORSHIP_POLICY, placementAvailable, safeSponsorUrl };
@@ -1,10 +1,10 @@
1
1
  "use client";
2
- import { setupNetworkConsentDelegation, checkUrlConsentBridge, hasConsented, isGeoConsentRequired, queryNetworkConsentHub, DEFAULT_CONSENT_HUB_URL, acceptAllCookies, rejectOptionalCookies, COOKIE_CONSENT_EVENT, recordConsentToCompliance, setNetworkConsentHub } from './chunk-UTBV6JJX.js';
2
+ import { hasConsented, rejectOptionalCookies, DEFAULT_CONSENT_HUB_URL, isGpcActive, COOKIE_CONSENT_EVENT, acceptAllCookies, recordConsentToCompliance } from './chunk-JV76ZEIA.js';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  function CookieConsentBanner({
7
- title = "Help Us Improve Our Website with Cookies",
7
+ title = "Your privacy choices",
8
8
  text,
9
9
  settingsUrl = "/cookies",
10
10
  className = "",
@@ -18,73 +18,41 @@ function CookieConsentBanner({
18
18
  const [visible, setVisible] = useState(false);
19
19
  useEffect(() => {
20
20
  setMounted(true);
21
- setupNetworkConsentDelegation();
22
- if (checkUrlConsentBridge()) {
23
- setVisible(false);
24
- return;
21
+ const url = new URL(window.location.href);
22
+ if (url.searchParams.has("sm_consent")) {
23
+ if (url.searchParams.get("sm_consent") === "0" && !hasConsented())
24
+ rejectOptionalCookies({ hubUrl: consentHubUrl });
25
+ url.searchParams.delete("sm_consent");
26
+ window.history.replaceState(window.history.state, "", url);
25
27
  }
26
- if (hasConsented()) {
27
- setVisible(false);
28
- return;
29
- }
30
- if (!forceShow && !isGeoConsentRequired(countryCode)) {
31
- setVisible(false);
32
- void queryNetworkConsentHub(consentHubUrl, 1200).then((networkStatus) => {
33
- if (networkStatus === "accepted") {
34
- acceptAllCookies();
35
- } else if (networkStatus === "rejected") {
36
- rejectOptionalCookies();
37
- }
38
- });
39
- return;
40
- }
41
- let cancelled = false;
42
- void queryNetworkConsentHub(consentHubUrl, 1e3).then((networkStatus) => {
43
- if (cancelled) return;
44
- if (networkStatus === "accepted") {
45
- acceptAllCookies();
46
- setVisible(false);
47
- } else if (networkStatus === "rejected") {
48
- rejectOptionalCookies();
49
- setVisible(false);
50
- } else {
51
- setVisible(true);
52
- }
53
- });
54
- return () => {
55
- cancelled = true;
56
- };
28
+ setVisible(!hasConsented() && !isGpcActive());
57
29
  }, [countryCode, forceShow, consentHubUrl]);
58
30
  useEffect(() => {
59
31
  const onConsentChange = () => {
60
- if (hasConsented()) {
61
- setVisible(false);
62
- }
32
+ setVisible(!hasConsented() && !isGpcActive());
63
33
  };
64
34
  window.addEventListener(COOKIE_CONSENT_EVENT, onConsentChange);
65
35
  return () => window.removeEventListener(COOKIE_CONSENT_EVENT, onConsentChange);
66
36
  }, []);
67
37
  if (!mounted || !visible) return null;
68
38
  const handleAccept = () => {
69
- const record = acceptAllCookies();
39
+ const record = acceptAllCookies({ hubUrl: consentHubUrl });
70
40
  setVisible(false);
71
41
  void recordConsentToCompliance(record, {
72
42
  endpoint: complianceEndpoint,
73
43
  publicationSlug
74
44
  });
75
- setNetworkConsentHub("accepted", consentHubUrl);
76
45
  };
77
46
  const handleReject = () => {
78
- const record = rejectOptionalCookies();
47
+ const record = rejectOptionalCookies({ hubUrl: consentHubUrl });
79
48
  setVisible(false);
80
49
  void recordConsentToCompliance(record, {
81
50
  endpoint: complianceEndpoint,
82
51
  publicationSlug
83
52
  });
84
- setNetworkConsentHub("rejected", consentHubUrl);
85
53
  };
86
54
  const defaultText = /* @__PURE__ */ jsxs(Fragment, { children: [
87
- "We use cookies and device data to analyze performance, support local sponsors, and remember your reading preferences across our news network. View",
55
+ "With your permission, we measure reading activity and sponsor acknowledgments. You can read the publication with optional cookies turned off. View",
88
56
  " ",
89
57
  /* @__PURE__ */ jsx("a", { href: settingsUrl, className: "sm-cookie-banner-link", children: "Cookie Settings" }),
90
58
  " ",
@@ -1,5 +1,5 @@
1
1
  import { recordConsentToCompliance as recordConsentToCompliance$1, getCookieConsent, decorateNetworkUrl } from '@scalemule/compliance';
2
- export { COOKIE_CONSENT_BACKUP_KEY, COOKIE_CONSENT_EVENT, COOKIE_CONSENT_KEY, COOKIE_CONSENT_MAX_AGE_SECONDS, DEFAULT_CONSENT_HUB_URL, DEFAULT_PREFERENCES_ACCEPTED, DEFAULT_PREFERENCES_REJECTED, EU_EEA_UK_COUNTRIES, NETWORK_CONSENT_STORAGE_KEY, acceptAllCookies, checkUrlConsentBridge, clearCookieConsent, decorateNetworkUrl, getCookieConsent, hasConsented, isCategoryAllowed, isGeoConsentRequired, queryNetworkConsentHub, rejectOptionalCookies, setCookieConsent, setNetworkConsentHub } from '@scalemule/compliance';
2
+ export { COOKIE_CONSENT_BACKUP_KEY, COOKIE_CONSENT_EVENT, COOKIE_CONSENT_KEY, COOKIE_CONSENT_MAX_AGE_SECONDS, DEFAULT_CONSENT_HUB_URL, DEFAULT_PREFERENCES_ACCEPTED, DEFAULT_PREFERENCES_REJECTED, EU_EEA_UK_COUNTRIES, NETWORK_CONSENT_STORAGE_KEY, acceptAllCookies, checkUrlConsentBridge, clearCookieConsent, decorateNetworkUrl, getCookieConsent, hasConsented, isCategoryAllowed, isGeoConsentRequired, isGpcActive, queryNetworkConsentHub, rejectOptionalCookies, setCookieConsent, setNetworkConsentHub } from '@scalemule/compliance';
3
3
 
4
4
  // src/cookies.ts
5
5
  async function recordConsentToCompliance(record, options) {
@@ -48,13 +48,6 @@ var COOKIE_CATEGORIES = [
48
48
  duration: "1 year",
49
49
  type: "HTTP Cookie"
50
50
  },
51
- {
52
- name: "napsite_session_v1",
53
- provider: "First-Party",
54
- purpose: "Maintains session continuity, security tokens, and server routing.",
55
- duration: "30 minutes (idle)",
56
- type: "Session Storage"
57
- },
58
51
  {
59
52
  name: "napsite_preview",
60
53
  provider: "First-Party",
@@ -68,9 +61,16 @@ var COOKIE_CATEGORIES = [
68
61
  id: "performance",
69
62
  title: "Performance & Analytics Cookies",
70
63
  shortDescription: "Help us measure reader engagement, story completion, and site reliability.",
71
- fullDescription: "These cookies collect anonymous information about how visitors navigate our news publication. They allow us to count article reads, understand scroll depth and reading completion, and identify broken links or slow-loading assets so we can keep our community reporting responsive and fast. All metrics are aggregated and never contain personal information.",
64
+ fullDescription: "With your permission, first-party identifiers support page-visit and reading measurements. Aggregate reports help us improve the publication. Measurements are incomplete when readers decline consent and are not a count of unique people.",
72
65
  required: false,
73
66
  cookies: [
67
+ {
68
+ name: "napsite_session_v1",
69
+ provider: "First-Party",
70
+ purpose: "Groups consented reading measurements within a session.",
71
+ duration: "30 minutes (idle)",
72
+ type: "Session Storage"
73
+ },
74
74
  {
75
75
  name: "napsite_visitor_v1",
76
76
  provider: "First-Party",
@@ -120,25 +120,10 @@ var COOKIE_CATEGORIES = [
120
120
  {
121
121
  id: "advertising",
122
122
  title: "Advertising & Local Sponsorship Cookies",
123
- shortDescription: "Support local business sponsors by capping repetition and measuring notices.",
124
- fullDescription: "Our journalism is supported by local business sponsors and community partners. These cookies ensure you do not see the same sponsor banner repeatedly (frequency capping) and help local merchants measure whether their announcement reached their community. They never track your activity across unrelated third-party websites or build external advertising profiles.",
123
+ shortDescription: "Measure clearly labeled community sponsorship views and link clicks.",
124
+ fullDescription: "With your permission, we measure visible sponsor acknowledgments and link clicks. Repetition limits use temporary page-session memory. We do not use third-party advertising trackers or build behavioral advertising profiles.",
125
125
  required: false,
126
- cookies: [
127
- {
128
- name: "napsite_sponsor_cap",
129
- provider: "First-Party",
130
- purpose: "Prevents repetitive display of identical local business announcements.",
131
- duration: "7 days",
132
- type: "Local Storage"
133
- },
134
- {
135
- name: "local_sponsor_ref",
136
- provider: "First-Party",
137
- purpose: "Attributes community inquiries directly to the sponsoring local merchant.",
138
- duration: "30 days",
139
- type: "Local Storage"
140
- }
141
- ]
126
+ cookies: []
142
127
  }
143
128
  ];
144
129
 
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { getCookieConsent, DEFAULT_PREFERENCES_ACCEPTED, COOKIE_CATEGORIES, setCookieConsent, recordConsentToCompliance, DEFAULT_PREFERENCES_REJECTED } from './chunk-UTBV6JJX.js';
2
+ import { getCookieConsent, DEFAULT_PREFERENCES_ACCEPTED, COOKIE_CATEGORIES, setCookieConsent, recordConsentToCompliance, DEFAULT_PREFERENCES_REJECTED } from './chunk-JV76ZEIA.js';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5
 
@@ -1,4 +1,4 @@
1
- import { NETWORK_PARENT } from './chunk-UTBV6JJX.js';
1
+ import { NETWORK_PARENT } from './chunk-JV76ZEIA.js';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
 
4
4
  function NetworkCopyrightNotice({
@@ -114,7 +114,7 @@ var listedPublications = localPublications.filter(
114
114
  listedPublications.filter(
115
115
  (publication) => publication.slug !== "bayareachronicle"
116
116
  );
117
- var NETWORK_HOSTNAMES = new Set(
117
+ new Set(
118
118
  localPublications.map((p) => {
119
119
  try {
120
120
  return new URL(p.url).hostname.replace(/^www\./, "").toLowerCase();
@@ -123,46 +123,13 @@ var NETWORK_HOSTNAMES = new Set(
123
123
  }
124
124
  })
125
125
  );
126
- function isNetworkHostname(hostname) {
127
- if (!hostname) return false;
128
- const clean = hostname.replace(/^www\./, "").toLowerCase();
129
- return clean === "bayareanewsnetwork.com" || clean.endsWith(".bayareanewsnetwork.com") || NETWORK_HOSTNAMES.has(clean) || clean.endsWith(".bayareachronicle.com") || clean.endsWith(".napsite.com") || clean.endsWith(".site.scalemule.com");
130
- }
131
126
 
132
127
  // src/cookies.ts
133
128
  async function recordConsentToCompliance(record, options) {
134
129
  return compliance.recordConsentToCompliance(record, options);
135
130
  }
136
- var delegationInstalled = false;
137
- function setupNetworkConsentDelegation() {
138
- if (typeof window === "undefined" || delegationInstalled) return;
139
- delegationInstalled = true;
140
- document.addEventListener(
141
- "click",
142
- (e) => {
143
- const target = e.target;
144
- const anchor = target?.closest("a");
145
- if (!anchor || !anchor.href) return;
146
- try {
147
- const url = new URL(anchor.href, window.location.href);
148
- if (url.protocol !== "http:" && url.protocol !== "https:") return;
149
- if (isNetworkHostname(url.hostname)) {
150
- const consent = compliance.getCookieConsent();
151
- if (consent) {
152
- const decorated = compliance.decorateNetworkUrl(anchor.href);
153
- if (decorated !== anchor.href) {
154
- anchor.href = decorated;
155
- }
156
- }
157
- }
158
- } catch {
159
- }
160
- },
161
- { capture: true }
162
- );
163
- }
164
131
  function CookieConsentBanner({
165
- title = "Help Us Improve Our Website with Cookies",
132
+ title = "Your privacy choices",
166
133
  text,
167
134
  settingsUrl = "/cookies",
168
135
  className = "",
@@ -176,73 +143,41 @@ function CookieConsentBanner({
176
143
  const [visible, setVisible] = react.useState(false);
177
144
  react.useEffect(() => {
178
145
  setMounted(true);
179
- setupNetworkConsentDelegation();
180
- if (compliance.checkUrlConsentBridge()) {
181
- setVisible(false);
182
- return;
146
+ const url = new URL(window.location.href);
147
+ if (url.searchParams.has("sm_consent")) {
148
+ if (url.searchParams.get("sm_consent") === "0" && !compliance.hasConsented())
149
+ compliance.rejectOptionalCookies({ hubUrl: consentHubUrl });
150
+ url.searchParams.delete("sm_consent");
151
+ window.history.replaceState(window.history.state, "", url);
183
152
  }
184
- if (compliance.hasConsented()) {
185
- setVisible(false);
186
- return;
187
- }
188
- if (!forceShow && !compliance.isGeoConsentRequired(countryCode)) {
189
- setVisible(false);
190
- void compliance.queryNetworkConsentHub(consentHubUrl, 1200).then((networkStatus) => {
191
- if (networkStatus === "accepted") {
192
- compliance.acceptAllCookies();
193
- } else if (networkStatus === "rejected") {
194
- compliance.rejectOptionalCookies();
195
- }
196
- });
197
- return;
198
- }
199
- let cancelled = false;
200
- void compliance.queryNetworkConsentHub(consentHubUrl, 1e3).then((networkStatus) => {
201
- if (cancelled) return;
202
- if (networkStatus === "accepted") {
203
- compliance.acceptAllCookies();
204
- setVisible(false);
205
- } else if (networkStatus === "rejected") {
206
- compliance.rejectOptionalCookies();
207
- setVisible(false);
208
- } else {
209
- setVisible(true);
210
- }
211
- });
212
- return () => {
213
- cancelled = true;
214
- };
153
+ setVisible(!compliance.hasConsented() && !compliance.isGpcActive());
215
154
  }, [countryCode, forceShow, consentHubUrl]);
216
155
  react.useEffect(() => {
217
156
  const onConsentChange = () => {
218
- if (compliance.hasConsented()) {
219
- setVisible(false);
220
- }
157
+ setVisible(!compliance.hasConsented() && !compliance.isGpcActive());
221
158
  };
222
159
  window.addEventListener(compliance.COOKIE_CONSENT_EVENT, onConsentChange);
223
160
  return () => window.removeEventListener(compliance.COOKIE_CONSENT_EVENT, onConsentChange);
224
161
  }, []);
225
162
  if (!mounted || !visible) return null;
226
163
  const handleAccept = () => {
227
- const record = compliance.acceptAllCookies();
164
+ const record = compliance.acceptAllCookies({ hubUrl: consentHubUrl });
228
165
  setVisible(false);
229
166
  void recordConsentToCompliance(record, {
230
167
  endpoint: complianceEndpoint,
231
168
  publicationSlug
232
169
  });
233
- compliance.setNetworkConsentHub("accepted", consentHubUrl);
234
170
  };
235
171
  const handleReject = () => {
236
- const record = compliance.rejectOptionalCookies();
172
+ const record = compliance.rejectOptionalCookies({ hubUrl: consentHubUrl });
237
173
  setVisible(false);
238
174
  void recordConsentToCompliance(record, {
239
175
  endpoint: complianceEndpoint,
240
176
  publicationSlug
241
177
  });
242
- compliance.setNetworkConsentHub("rejected", consentHubUrl);
243
178
  };
244
179
  const defaultText = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
245
- "We use cookies and device data to analyze performance, support local sponsors, and remember your reading preferences across our news network. View",
180
+ "With your permission, we measure reading activity and sponsor acknowledgments. You can read the publication with optional cookies turned off. View",
246
181
  " ",
247
182
  /* @__PURE__ */ jsxRuntime.jsx("a", { href: settingsUrl, className: "sm-cookie-banner-link", children: "Cookie Settings" }),
248
183
  " ",
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- export { CookieConsentBanner } from './chunk-2IYKWGVM.js';
3
- import './chunk-UTBV6JJX.js';
2
+ export { CookieConsentBanner } from './chunk-GOWOYMSG.js';
3
+ import './chunk-JV76ZEIA.js';
@@ -143,13 +143,6 @@ var COOKIE_CATEGORIES = [
143
143
  duration: "1 year",
144
144
  type: "HTTP Cookie"
145
145
  },
146
- {
147
- name: "napsite_session_v1",
148
- provider: "First-Party",
149
- purpose: "Maintains session continuity, security tokens, and server routing.",
150
- duration: "30 minutes (idle)",
151
- type: "Session Storage"
152
- },
153
146
  {
154
147
  name: "napsite_preview",
155
148
  provider: "First-Party",
@@ -163,9 +156,16 @@ var COOKIE_CATEGORIES = [
163
156
  id: "performance",
164
157
  title: "Performance & Analytics Cookies",
165
158
  shortDescription: "Help us measure reader engagement, story completion, and site reliability.",
166
- fullDescription: "These cookies collect anonymous information about how visitors navigate our news publication. They allow us to count article reads, understand scroll depth and reading completion, and identify broken links or slow-loading assets so we can keep our community reporting responsive and fast. All metrics are aggregated and never contain personal information.",
159
+ fullDescription: "With your permission, first-party identifiers support page-visit and reading measurements. Aggregate reports help us improve the publication. Measurements are incomplete when readers decline consent and are not a count of unique people.",
167
160
  required: false,
168
161
  cookies: [
162
+ {
163
+ name: "napsite_session_v1",
164
+ provider: "First-Party",
165
+ purpose: "Groups consented reading measurements within a session.",
166
+ duration: "30 minutes (idle)",
167
+ type: "Session Storage"
168
+ },
169
169
  {
170
170
  name: "napsite_visitor_v1",
171
171
  provider: "First-Party",
@@ -215,25 +215,10 @@ var COOKIE_CATEGORIES = [
215
215
  {
216
216
  id: "advertising",
217
217
  title: "Advertising & Local Sponsorship Cookies",
218
- shortDescription: "Support local business sponsors by capping repetition and measuring notices.",
219
- fullDescription: "Our journalism is supported by local business sponsors and community partners. These cookies ensure you do not see the same sponsor banner repeatedly (frequency capping) and help local merchants measure whether their announcement reached their community. They never track your activity across unrelated third-party websites or build external advertising profiles.",
218
+ shortDescription: "Measure clearly labeled community sponsorship views and link clicks.",
219
+ fullDescription: "With your permission, we measure visible sponsor acknowledgments and link clicks. Repetition limits use temporary page-session memory. We do not use third-party advertising trackers or build behavioral advertising profiles.",
220
220
  required: false,
221
- cookies: [
222
- {
223
- name: "napsite_sponsor_cap",
224
- provider: "First-Party",
225
- purpose: "Prevents repetitive display of identical local business announcements.",
226
- duration: "7 days",
227
- type: "Local Storage"
228
- },
229
- {
230
- name: "local_sponsor_ref",
231
- provider: "First-Party",
232
- purpose: "Attributes community inquiries directly to the sponsoring local merchant.",
233
- duration: "30 days",
234
- type: "Local Storage"
235
- }
236
- ]
221
+ cookies: []
237
222
  }
238
223
  ];
239
224
  function CookieSettingsView({
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- export { CookieSettingsView } from './chunk-72PKW2HM.js';
3
- import './chunk-UTBV6JJX.js';
2
+ export { CookieSettingsView } from './chunk-UL2Q3N26.js';
3
+ import './chunk-JV76ZEIA.js';