From 75474d5151be425f276ce127f8a3949d618c0fa3 Mon Sep 17 00:00:00 2001 From: Etienne Latendresse Date: Mon, 13 Apr 2026 13:38:03 -0400 Subject: [PATCH 1/5] add pub.ts template with CI checks --- .github/workflows/release.yml | 27 ++++- .github/workflows/reusable-lint-test.yml | 21 ++++ browser/pub.ts | 141 +++++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 browser/pub.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9e3966f..4bf9eca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -123,6 +123,31 @@ jobs: headers: | x-goog-meta-optable-sdk-version: ${{ github.ref_name }} + deploy-pub-template-to-gcs: + needs: [build] + runs-on: ubuntu-22.04 + permissions: + contents: read + id-token: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Auth to google cloud + uses: google-github-actions/auth@v2 + with: + workload_identity_provider: ${{ env.workload_identity_provider }} + service_account: ${{ env.service-account }} + + - name: Upload pub.ts template to GCS bucket + uses: google-github-actions/upload-cloud-storage@v2 + with: + path: "browser/pub.ts" + destination: "optable-web-sdk/pub-sdk/${{ github.ref_name }}" + process_gcloudignore: false + headers: | + x-goog-meta-optable-sdk-version: ${{ github.ref_name }} + deploy-demo: needs: [deploy-sdk-to-npm] permissions: @@ -181,7 +206,7 @@ jobs: run: docker push us-docker.pkg.dev/optable-artifact-registry/optable/optable-web-sdk-demos:${{ github.ref_name }} slack-notification: - needs: [tests-prettier, build, deploy-sdk-to-npm, define-gcs-versions-to-update, deploy-sdk-to-gcs, deploy-demo] + needs: [tests-prettier, build, deploy-sdk-to-npm, define-gcs-versions-to-update, deploy-sdk-to-gcs, deploy-pub-template-to-gcs, deploy-demo] runs-on: ubuntu-22.04 if: ${{ failure() }} steps: diff --git a/.github/workflows/reusable-lint-test.yml b/.github/workflows/reusable-lint-test.yml index 655d11d..dfb84dd 100644 --- a/.github/workflows/reusable-lint-test.yml +++ b/.github/workflows/reusable-lint-test.yml @@ -14,6 +14,27 @@ jobs: - name: Test run: pnpm test + validate-pub-template: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check if pub template files changed + id: changed + run: | + if git diff --name-only origin/master...HEAD | grep -qE '^(browser/pub\.ts|scripts/validate-pub-template\.sh)$'; then + echo "pub_changed=true" >> "$GITHUB_OUTPUT" + else + echo "pub_changed=false" >> "$GITHUB_OUTPUT" + fi + + - name: Validate pub.ts template + if: steps.changed.outputs.pub_changed == 'true' + run: ./scripts/validate-pub-template.sh + prettier: runs-on: ubuntu-22.04 steps: diff --git a/browser/pub.ts b/browser/pub.ts new file mode 100644 index 0000000..eadae98 --- /dev/null +++ b/browser/pub.ts @@ -0,0 +1,141 @@ +// browser/pub.ts — Go text/template + TypeScript +// This file is processed by Go text/template BEFORE esbuild compilation. +// It is NOT valid TypeScript until template directives are resolved. +// +// Template variables: +// .Host - Edge API hostname (e.g. "ca.edge.optable.co") +// .Site - Site slug derived from origin +// .Node - Node slug derived from tenant +// .Timeout - Optional timeout hint (e.g. "500ms", "2s") +// .PrebidGlobal - Prebid.js global variable name (e.g. "pbjs", "__pmc_atlasmg_pbjs") +// .EnableSecureSignals - Boolean: enable GPT Secure Signals +// .EnableBotDetection - Boolean: enable bot detection +// .EnableAnalytics - Boolean: enable Prebid analytics +// .GeoTargeting - "regional" or "multi-region" + +import OptableSDK from "@optable/web-sdk"; +{{if .EnableAnalytics}} +import OptablePrebidAnalytics from "@optable/web-sdk/lib/dist/addons/prebid/analytics"; +{{end}} + +declare global { + interface Window { + optable?: Record; + } +} + +// --- Commands queue (executes queued functions immediately) --- +class OptableCommands { + constructor(cmds: OptableCommands | Function[]) { + if (Array.isArray(cmds)) { + for (const cmd of cmds) { + if (typeof cmd === "function") cmd(); + } + } + } + push(cmd: Function) { + cmd(); + } +} + +// --- Debug logging --- +function optableMessage(...args: unknown[]) { + if (sessionStorage.optableDebug) { + console.log("[OPTABLE WRAPPER]", ...args); + } +} + +// --- URL query feature flags --- +function setOptableFlagsFromURLQuery() { + const keys = ["optableDebug", "optableDisableConsent", "optableResolveTD", "optableEnableAnalytics"]; + const search = window.location.search || ""; + keys.forEach((key) => { + if (search.match(new RegExp(key, "g"))) { + sessionStorage.setItem(key, "1"); + } + }); +} + +// --- Consent handling --- +function getConsent() { + if (sessionStorage.optableDisableConsent) { + return { + createProfilesForAdvertising: true, + deviceAccess: true, + measureAdvertisingPerformance: true, + reg: null, + useProfilesForAdvertising: true, + }; + } + return { cmpapi: {} }; +} + +{{if .EnableAnalytics}} +// --- Analytics initialization --- +function initPrebidAnalytics(sdk: OptableSDK) { + const pbjsObject = (window as any)["{{.PrebidGlobal}}"] || (window as any)["pbjs"]; + if (!pbjsObject) return; + + const analyticsSDK = new OptableSDK({ + host: "{{.Host}}", + node: "analytics", + site: "analytics", + readOnly: true, + cookies: false, + }); + + const analytics = new OptablePrebidAnalytics(analyticsSDK, { + analytics: true, + tenant: "{{.Node}}", + debug: !!sessionStorage.optableDebug, + samplingRate: 0.1, + }); + + analytics.hookIntoPrebid(pbjsObject); +} +{{end}} + +// --- Main execution --- +(function run() { + setOptableFlagsFromURLQuery(); + + window.optable = window.optable || {}; + window.optable.SDK = OptableSDK; + + const consent = getConsent(); + const sdk = new OptableSDK({ + host: "{{.Host}}", + site: "{{.Site}}", + node: "{{.Node}}", + cookies: false, + consent, + initPassport: false, + {{- if .Timeout}} + timeout: "{{.Timeout}}", + {{- end}} + }); + + window.optable["{{.Node}}_instance"] = sdk; + + {{if .EnableSecureSignals}} + optableMessage("Enabling secure signals"); + sdk.installGPTSecureSignals(); + {{end}} + + {{if .EnableBotDetection}} + optableMessage("Enabling bot detection"); + (sdk as any).enableBotDetection(); + {{end}} + + {{if eq .GeoTargeting "multi-region"}} + optableMessage("Multi-region mode: reading window.optable.countryCode"); + (sdk as any).setCountryCodeFromGlobal(); + {{end}} + + {{if .EnableAnalytics}} + initPrebidAnalytics(sdk); + {{end}} + + window.optable.cmd = new OptableCommands(window.optable.cmd || []); + optableMessage("SDK initialized"); +})(); From 02d40e64a93349a90efcea7430458fe53702dc7f Mon Sep 17 00:00:00 2001 From: Etienne Latendresse Date: Mon, 13 Apr 2026 13:43:30 -0400 Subject: [PATCH 2/5] add prettierignore for pub.ts and validation script --- .prettierignore | 3 ++ scripts/validate-pub-template.sh | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100755 scripts/validate-pub-template.sh diff --git a/.prettierignore b/.prettierignore index 7c81f7a..492f636 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,9 @@ # build outputs browser/dist + +# Go text/template file (not valid TypeScript) +browser/pub.ts lib/dist # demos diff --git a/scripts/validate-pub-template.sh b/scripts/validate-pub-template.sh new file mode 100755 index 0000000..1daff28 --- /dev/null +++ b/scripts/validate-pub-template.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Validates that browser/pub.ts renders to compilable TypeScript. +# +# This script simulates Go text/template rendering by replacing template +# directives with sample values, then compiles the result with esbuild +# to catch syntax errors before they reach a release. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +TEMPLATE="${REPO_ROOT}/browser/pub.ts" +WORKDIR="$(mktemp -d)" + +trap 'rm -rf "${WORKDIR}"' EXIT + +echo "Validating pub.ts template..." + +# Render template with sample config values. +# Features that depend on SDK methods not yet implemented are disabled. +rendered="${WORKDIR}/pub.ts" + +sed \ + -e '/{{if/d' \ + -e '/{{end}}/d' \ + -e 's/{{- if [^}]*}}//' \ + -e 's/{{- end}}//' \ + -e 's/{{\.Host}}/sample.edge.example.co/g' \ + -e 's/{{\.Site}}/sample-site/g' \ + -e 's/{{\.Node}}/sample-node/g' \ + -e 's/{{\.PrebidGlobal}}/pbjs/g' \ + -e 's/{{\.Timeout}}/500ms/g' \ + "${TEMPLATE}" > "${rendered}" + +echo "Rendered template to ${rendered}" + +# Compile with esbuild to verify the output is valid TypeScript. +# @optable/web-sdk is marked external since it's resolved at bundle time (Phase 5). +npx --yes esbuild "${rendered}" \ + --bundle \ + --format=iife \ + --platform=browser \ + --target=es2015 \ + --external:@optable/web-sdk \ + --external:@optable/web-sdk/* \ + --outfile="${WORKDIR}/pub.js" + +echo "Template validation passed: pub.ts renders to compilable TypeScript." From 2f741583f3fd3035a8b408723654396d0ef86be2 Mon Sep 17 00:00:00 2001 From: Etienne Latendresse Date: Mon, 13 Apr 2026 13:48:49 -0400 Subject: [PATCH 3/5] made deploy step more similar to existing --- .github/workflows/release.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4bf9eca..90442af 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -124,7 +124,10 @@ jobs: x-goog-meta-optable-sdk-version: ${{ github.ref_name }} deploy-pub-template-to-gcs: - needs: [build] + needs: [deploy-sdk-to-npm, define-gcs-versions-to-update] + strategy: + matrix: + sdk-version: ${{ fromJSON(needs.define-gcs-versions-to-update.outputs.sdk-versions) }} runs-on: ubuntu-22.04 permissions: contents: read @@ -143,7 +146,7 @@ jobs: uses: google-github-actions/upload-cloud-storage@v2 with: path: "browser/pub.ts" - destination: "optable-web-sdk/pub-sdk/${{ github.ref_name }}" + destination: "optable-web-sdk/pub-sdk/${{ matrix.sdk-version }}" process_gcloudignore: false headers: | x-goog-meta-optable-sdk-version: ${{ github.ref_name }} From 1ce3e2c1290c4459f21e8aa8318eabed32e6daf7 Mon Sep 17 00:00:00 2001 From: Etienne Latendresse Date: Mon, 13 Apr 2026 14:47:49 -0400 Subject: [PATCH 4/5] apply prettier changes --- .github/workflows/release.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90442af..8a44d9c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -209,7 +209,16 @@ jobs: run: docker push us-docker.pkg.dev/optable-artifact-registry/optable/optable-web-sdk-demos:${{ github.ref_name }} slack-notification: - needs: [tests-prettier, build, deploy-sdk-to-npm, define-gcs-versions-to-update, deploy-sdk-to-gcs, deploy-pub-template-to-gcs, deploy-demo] + needs: + [ + tests-prettier, + build, + deploy-sdk-to-npm, + define-gcs-versions-to-update, + deploy-sdk-to-gcs, + deploy-pub-template-to-gcs, + deploy-demo, + ] runs-on: ubuntu-22.04 if: ${{ failure() }} steps: From caf16c168f1dc36a74175331fdb569727b21aafd Mon Sep 17 00:00:00 2001 From: Etienne Latendresse Date: Mon, 13 Apr 2026 15:01:41 -0400 Subject: [PATCH 5/5] add vendor id --- browser/pub.ts | 11 ++++++++++- scripts/validate-pub-template.sh | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/browser/pub.ts b/browser/pub.ts index eadae98..fb588da 100644 --- a/browser/pub.ts +++ b/browser/pub.ts @@ -8,6 +8,8 @@ // .Node - Node slug derived from tenant // .Timeout - Optional timeout hint (e.g. "500ms", "2s") // .PrebidGlobal - Prebid.js global variable name (e.g. "pbjs", "__pmc_atlasmg_pbjs") +// .TcfeuVendorID - Optional TCF EU vendor ID (GVLID) for consent checks +// .TcfcaVendorID - Optional TCF CA vendor ID (GVLID) for consent checks // .EnableSecureSignals - Boolean: enable GPT Secure Signals // .EnableBotDetection - Boolean: enable bot detection // .EnableAnalytics - Boolean: enable Prebid analytics @@ -67,7 +69,14 @@ function getConsent() { useProfilesForAdvertising: true, }; } - return { cmpapi: {} }; + return { cmpapi: { + {{- if .TcfeuVendorID}} + tcfeuVendorID: {{.TcfeuVendorID}}, + {{- end}} + {{- if .TcfcaVendorID}} + tcfcaVendorID: {{.TcfcaVendorID}}, + {{- end}} + } }; } {{if .EnableAnalytics}} diff --git a/scripts/validate-pub-template.sh b/scripts/validate-pub-template.sh index 1daff28..dc3928d 100755 --- a/scripts/validate-pub-template.sh +++ b/scripts/validate-pub-template.sh @@ -30,6 +30,8 @@ sed \ -e 's/{{\.Node}}/sample-node/g' \ -e 's/{{\.PrebidGlobal}}/pbjs/g' \ -e 's/{{\.Timeout}}/500ms/g' \ + -e 's/{{\.TcfeuVendorID}}/123/g' \ + -e 's/{{\.TcfcaVendorID}}/456/g' \ "${TEMPLATE}" > "${rendered}" echo "Rendered template to ${rendered}"