From a2ac57b080318f2e4b782ade6dcbd7ffc755db89 Mon Sep 17 00:00:00 2001 From: GotPop Date: Tue, 14 Jul 2026 15:13:45 +0100 Subject: [PATCH 1/7] Shaders MCP client --- .vscode/mcp.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .vscode/mcp.json diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 00000000..93759f37 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,8 @@ +{ + "servers": { + "shaders": { + "type": "http", + "url": "https://shaders.com/mcp" + } + } +} \ No newline at end of file From 50e9378fa0b800675c3449a7e3f1afda91bb9317 Mon Sep 17 00:00:00 2001 From: GotPop Date: Mon, 7 Sep 2026 16:33:23 +0100 Subject: [PATCH 2/7] Adding linked in tag tracking --- .github/instructions/php.instructions.md | 1 + README.md | 1 + functions.php | 1 + inc/analytics-linkedin.php | 109 +++++++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 inc/analytics-linkedin.php diff --git a/.github/instructions/php.instructions.md b/.github/instructions/php.instructions.md index 76df1cf7..b2143ee2 100644 --- a/.github/instructions/php.instructions.md +++ b/.github/instructions/php.instructions.md @@ -111,6 +111,7 @@ All PHP lives in `inc/` and is loaded via `functions.php`. Each file handles **o | `analytics-ga4.php` | GA4 registration + output | | `analytics-leadfeeder.php` | Leadfeeder registration + output | | `analytics-cookiebot.php` | CookieBot registration + output | +| `analytics-linkedin.php` | LinkedIn Insight Tag registration + output | | `theme-settings.php` | Settings page + sections | | `theme-settings-footer.php` | Footer content fields | diff --git a/README.md b/README.md index d7a80cfd..14a84e17 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Each file handles **one concern**: | `analytics-ga4.php` | GA4 registration + output | | `analytics-leadfeeder.php` | Leadfeeder registration + output | | `analytics-cookiebot.php` | CookieBot registration + output | +| `analytics-linkedin.php` | LinkedIn Insight Tag registration + output | All functions are **fully typed** (parameter + return types). PHPStan runs at level 5 in CI to prevent type regressions. diff --git a/functions.php b/functions.php index cb69b037..3dd20929 100644 --- a/functions.php +++ b/functions.php @@ -14,6 +14,7 @@ require get_template_directory() . '/inc/analytics-ga4.php'; require get_template_directory() . '/inc/analytics-leadfeeder.php'; require get_template_directory() . '/inc/analytics-cookiebot.php'; +require get_template_directory() . '/inc/analytics-linkedin.php'; require get_template_directory() . '/inc/theme-settings.php'; require get_template_directory() . '/inc/theme-settings-footer.php'; require get_template_directory() . '/inc/image-optimization.php'; diff --git a/inc/analytics-linkedin.php b/inc/analytics-linkedin.php new file mode 100644 index 00000000..57c492ae --- /dev/null +++ b/inc/analytics-linkedin.php @@ -0,0 +1,109 @@ +. + */ + +add_action( 'admin_init', 'observata_linkedin_register_setting' ); +add_action( 'wp_head', 'observata_output_linkedin_script', 100 ); + +// ───────────────────────────────────────────────────────────────── + +// Register the LinkedIn Partner ID setting and admin field. +function observata_linkedin_register_setting(): void { + register_setting( + 'observata_settings', + 'observata_linkedin_id', + array( + 'type' => 'string', + 'sanitize_callback' => 'observata_sanitize_linkedin_id', + 'default' => '', + ) + ); + + add_settings_field( + 'observata_linkedin_id', + __( 'LinkedIn Partner ID', 'observata' ), + 'observata_linkedin_id_field', + 'observata-settings', + 'observata_analytics_section' + ); +} + +// Sanitize and validate the LinkedIn Partner ID format. +function observata_sanitize_linkedin_id( string $value ): string { + $value = sanitize_text_field( $value ); + + if ( $value && ! preg_match( '/^[0-9]+$/', $value ) ) { + add_settings_error( + 'observata_linkedin_id', + 'invalid-linkedin-id', + __( 'Invalid LinkedIn Partner ID. Expected digits only.', 'observata' ) + ); + + return ''; + } + + return $value; +} + +// Render the LinkedIn Partner ID input field. +function observata_linkedin_id_field(): void { + $value = get_option( 'observata_linkedin_id', '' ); + + printf( + '', + esc_attr( $value ) + ); + + printf( + '

%s

', + esc_html__( 'Enter your LinkedIn Partner ID (Insight Tag). Leave blank to disable.', 'observata' ) + ); +} + +// Output the consent-gated LinkedIn Insight Tag snippet in . +function observata_output_linkedin_script(): void { + if ( ! observata_is_production() ) { + return; + } + + $linkedin_id = get_option( 'observata_linkedin_id', '' ); + + if ( empty( $linkedin_id ) ) { + return; + } + + if ( is_admin() || wp_doing_ajax() ) { + return; + } + + // phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedScript -- consent-gated via CookieBot + printf( + ' + + + ', + esc_js( $linkedin_id ), + esc_attr( $linkedin_id ) + ); + // phpcs:enable +} From 9ee427cb02afd34778f5a325302d2a145f892ccf Mon Sep 17 00:00:00 2001 From: GotPop Date: Mon, 7 Sep 2026 16:57:35 +0100 Subject: [PATCH 3/7] Making contact iframe dynamic --- blocks/card-contact-form/block.json | 16 ++++----- src/card-contact-form/edit.jsx | 51 ++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/blocks/card-contact-form/block.json b/blocks/card-contact-form/block.json index 5f6c8718..904d3156 100644 --- a/blocks/card-contact-form/block.json +++ b/blocks/card-contact-form/block.json @@ -5,7 +5,9 @@ "title": "Card Contact Form", "category": "theme", "description": "Embedded contact form via Zoho.", - "parent": ["observata/section-contact"], + "parent": [ + "observata/section-contact" + ], "supports": { "html": false, "multiple": false @@ -18,10 +20,8 @@ }, "editorScript": "file:../../build/index.js", "editorStyle": "file:../../build/index.css", - "viewStyle": ["file:card-contact-form.css"], - "example": { - "attributes": { - "formUrl": "https://forms.zohopublic.eu/Observata/form/Contactusforwebsite/formperma/WZY4ixkroGhjj-TNFSI45yFNmi5QFNBVWTdBcPxWMTE" - } - } -} + "viewStyle": [ + "file:card-contact-form.css" + ], + "example": {} +} \ No newline at end of file diff --git a/src/card-contact-form/edit.jsx b/src/card-contact-form/edit.jsx index 8c5426b2..7d4e2447 100644 --- a/src/card-contact-form/edit.jsx +++ b/src/card-contact-form/edit.jsx @@ -1,20 +1,49 @@ -import { useBlockProps } from '@wordpress/block-editor'; +import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; +import { PanelBody, TextControl } from '@wordpress/components'; + import BlockLabel from '../components/block-label'; +import { __ } from '@wordpress/i18n'; -export default function CardContactFormEdit({ attributes: _attributes }) { +export default function CardContactFormEdit({ attributes, setAttributes }) { + const { formUrl } = attributes; const blockProps = useBlockProps({ className: 'contact-form-editor' }); + const formUrlControl = ( + setAttributes({ formUrl: value })} + help={__('Zoho form embed URL. Leave blank to hide the form.', 'observata')} + /> + ); + return ( -
- -
-
- 📝 -

- Zoho Contact Form — preview not available in editor -

+ <> + + + {formUrlControl} + + + +
+ {formUrlControl} +
+
+ 📝 +

+ Zoho Contact Form — preview not available in editor +

+ {formUrl && ( +

+ + {formUrl} + +

+ )} +
-
+ ); } From cd3f666f875ee7fc74594a6a8d11b7726fd18180 Mon Sep 17 00:00:00 2001 From: GotPop Date: Tue, 8 Sep 2026 10:58:01 +0100 Subject: [PATCH 4/7] Updating iframe length on mobile --- blocks/card-contact-form/card-contact-form.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocks/card-contact-form/card-contact-form.css b/blocks/card-contact-form/card-contact-form.css index dd9bcd7b..3ff4ab24 100644 --- a/blocks/card-contact-form/card-contact-form.css +++ b/blocks/card-contact-form/card-contact-form.css @@ -10,7 +10,7 @@ } .iframe-contact-form { - height: 699px; + height: 762px; @media (width >=64rem) { height: 600px; From 0532e41544f2447a54c574d52082af75fc8ca34b Mon Sep 17 00:00:00 2001 From: GotPop Date: Wed, 23 Sep 2026 10:48:55 +0100 Subject: [PATCH 5/7] Scoping text box trim to editor to fix plugin bug --- style-editor.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/style-editor.css b/style-editor.css index bd5fc867..02d34316 100644 --- a/style-editor.css +++ b/style-editor.css @@ -25,10 +25,7 @@ --stroke-sphere-line: 1px; } -h1, -h2, -h3, -h4 { +.editor-styles-wrapper :where(h1, h2, h3, h4) { text-box: trim-both cap alphabetic; margin-block: 0 1rem; color: var(--colour-grey-300); From 71f5fe3d05901089a48705f051afcb79a2dab1b0 Mon Sep 17 00:00:00 2001 From: GotPop Date: Wed, 7 Oct 2026 12:16:02 +0100 Subject: [PATCH 6/7] Moving icons inline --- src/card-geo-list/edit.jsx | 4 ---- src/card-geo-shader/edit.jsx | 4 ---- src/card-geo-tech/edit.jsx | 4 ---- src/card-geo/edit.jsx | 4 ---- src/card-simple/edit.jsx | 4 ---- src/card-table-features/edit.jsx | 20 ++++++-------------- src/components/graphic-select.css | 21 ++++++++++++++++++--- src/components/graphic-select.jsx | 15 +++++++++++---- 8 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/card-geo-list/edit.jsx b/src/card-geo-list/edit.jsx index e9f36b55..9dc51f03 100644 --- a/src/card-geo-list/edit.jsx +++ b/src/card-geo-list/edit.jsx @@ -7,7 +7,6 @@ import { useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import BlockLabel from '../components/block-label'; import ControlsLayout from '../components/controls-layout'; -import GeoIcon from '../components/geo-icon'; import GEO_ICON_OPTIONS from '../components/geo-icon-options'; import GraphicSelect from '../components/graphic-select'; @@ -37,9 +36,6 @@ export default function CardGeoListEdit({ attributes, setAttributes }) {
-
- -
-
- -
-
- -
-
- -
-
- -
setAttributes({ ['plan' + i + 'Description']: value })} /> - -
- -
- setAttributes({ ['plan' + i + 'Icon']: val })} - /> -
+ setAttributes({ ['plan' + i + 'Icon']: val })} + /> API (appearance: base-select). * * Supports rich option content — SVG icons, images, or plain text — rendered inside - * native