plugin-icon

Marcelo Site Connector

Places the Google tags a site needs, gives pages the description search engines show, and sends dead addresses to the page that replaced them.
Versione
1.14.4
Ultimo aggiornamento
Aug 12, 2026

Connecting a website to Google Search Console, Google Analytics or Google Tag Manager always ends the same way: a line of code has to go into the site’s <head>.

WordPress can be given permission to write posts, pages and media over its own REST API, but not to write there. So the last step of connecting any of those three is a person being asked to paste a snippet into a theme file or into an SEO plugin’s settings — and the person being asked is usually a business owner who paid somebody to build the site two years ago.

This plugin removes that step. Install it once, and Marcelo can place those tags itself.

What it does

  • Places up to three Google tags in the site’s <head> — a Search Console verification, an Analytics tag and a Tag Manager container — built from the identifier of each rather than from any markup it was handed.
  • Stores a description for a page that has none, and prints it as that page’s meta description — the sentence a search engine shows under the page in its results. WordPress core keeps no such field, and every SEO plugin uses its own hidden one, so a description written into any of those keys is invisible on a site running a different plugin.
  • Stores the title a page should go by in search results and in a browser tab, and hands it to WordPress through pre_get_document_title — the filter core publishes for exactly this, and the one every common SEO plugin uses. This is not the post’s own title: post_title is the name of the page in the admin and usually the heading a visitor reads, and changing it does not change the title a search engine shows on a site running any SEO plugin.
  • Stores a LocalBusiness schema block describing the business, as JSON-LD in the head of every page.
  • Stores redirects for addresses that no longer exist, and sends visitors on to the page that replaced them.
  • Reads and writes the layout of a page built with Elementor, so the text of such a page can be edited at all. WordPress keeps a page’s text in post_content; Elementor keeps its own copy in a protected postmeta field and prints that instead, so a write to post_content on an Elementor page succeeds and changes nothing a visitor reads.
  • Puts a tap-to-call bar in front of visitors: one fixed element carrying the business’s phone number as a tel: link, printed at wp_footer on every page. It is Marcelo’s own element and touches nothing the site already had, so clearing it removes it completely.
  • Reports how this site serves robots.txt, and — only where WordPress generates it — lets a named crawler back in that robots.txt was turning away. A robots.txt file sitting in the site’s root is refused rather than touched: the webserver serves that file directly and WordPress is never asked for one, so nothing a plugin does could change what a crawler reads.
  • Points a page’s canonical link back at the page itself, where the one on it names another website. This is the only thing here that displaces markup the site was already printing rather than adding markup of its own — see below for exactly how far that reaches, and where it stops.
  • Adds a translated page’s own link among its hreflang alternates where it is missing one — the one entry that says “this page is itself”. Nothing else in the head is touched: whatever else prints the page’s other alternates is left exactly as it is, and only the language code is stored — the address is always built from the page’s current request, never stored, so it stays correct if the domain ever changes.
  • Saves an oversized picture in the site’s own media library again at a smaller size, keeping the untouched original beside it so it can be put back. This is the only thing here that overwrites a file rather than a value in the database, and it is bounded accordingly: only an attachment this site really owns, only a file inside its own uploads directory, only when the file still weighs what the caller says it weighed, never a GIF or an SVG, and never at all on a host with no image library. A re-encode that came out larger is undone in full.
  • Draws a page that does not exist yet in this site’s own theme — header, navigation, styling and footer — from a title and some text, and hands the finished page back without storing any of it. Nothing is created: no post, no draft, no revision, no row of any kind. The page is assembled in memory for the length of one request, and the database is held read-only underneath it, so anything on the site that would ordinarily write while a page renders is refused rather than trusted.
  • Exposes all of it over the REST API to users who can already manage_options.

What it does not do

  • It does not phone home. No connection is ever made from this plugin to any server, including ours. Everything travels the other way, over your site’s own authenticated REST API.
  • It contains no tracking, analytics or telemetry of its own.
  • It stores no markup at all. Three identifiers are kept — a verification token, a G- measurement id, a GTM- container id — and nothing else. Google’s scripts are then loaded through wp_enqueue_script, from a URL this plugin builds, so no text a caller sends can reach a visitor’s browser: there is no path by which any is stored.
  • The schema field is held to a far narrower rule than the rest: exactly one <script type="application/ld+json"> whose body parses as JSON, re-encoded from the parsed value rather than stored as received. A field named for structured data that accepted arbitrary script would be a larger plugin than this one.
  • A page description is text and nothing else. Every tag is stripped on the way in and the value is escaped again on the way out. One that is too long is refused rather than cut — a description truncated mid-sentence is worse than the one the page did not have.
  • A page title is held to the same rule, and for a sharper reason: it is printed inside a <title> element, where a surviving < would close the element early and put whatever followed onto the page. It is never written to the post itself — nothing here calls wp_update_post, and no page is renamed.
  • A title element of its own is printed only on a theme that does not declare title-tag support, because on every other theme WordPress prints one itself and a second would give the page two. Where a theme with no such support echoes its own <title> into header.php, nothing here can reach it and the page ends up with two; Marcelo reads the page afterwards, sees the two, and takes its own title off again.
  • An Elementor layout is checked before a byte of it is stored: it has to parse as a JSON list of elements, each naming its own type. One that does not is refused, and one that is too large is refused rather than stored in part — half a layout is a blank page, and a blank page is worse than everything this route exists to fix put together. A page with no Elementor layout on it is refused too, because storing one would switch the builder on and replace what visitors already see.
  • It never redirects an address the site can answer. A stored redirect fires only where WordPress was about to show a 404, so it cannot hide a page that exists — and if a page ever returns at that address, the redirect stops on its own.
  • It cannot send a visitor to another website. Destinations are paths on this site and go through wp_safe_redirect.
  • A canonical override cannot point anywhere but this site. The fault it exists to correct is a page handing its ranking to a different website, so a route that could store one would be able to cause the exact thing it repairs.
  • It does not rewrite your pages to remove a canonical it did not put there, and it will not. Removing a tag that another hook has already printed means buffering and find-and-replacing the whole page’s HTML, which is a far larger and more dangerous mechanism than anything else in this plugin. Instead it removes WordPress core’s own canonical for that request and asks Yoast, Rank Math, SEOPress, All in One SEO and The SEO Framework — through the filters each of them publishes for this purpose — not to print theirs, then prints one. Where the tag comes from a theme with no filter, none of that reaches it and the page ends up with two; Marcelo reads the page afterwards, sees the two, and takes its own override off again.
  • It stores no robots.txt and no line of one. The setting holds crawler names — “somebody decided GPTBot may read this site” — and the change is made to the text WordPress itself generates, as it generates it. There is no path by which text a caller sends reaches that file.
  • It never writes a file. The only file it will ever name is the robots.txt in the site’s own root, worked out from ABSPATH and never taken from a request, and it is named in order to be refused rather than written.
  • It never removes a robots.txt rule that names a crawler nobody asked about. A rule shared between two crawlers is left exactly as it is, and the caller is told which others share it.
  • It never overrides “Discourage search engines from indexing this site” in Settings Reading. That setting is what closes robots.txt to everybody on nearly every WordPress site, it also puts a noindex on every page, and it is a decision somebody made on purpose — on a staging site or a site not ready to launch, the right one.
  • The availability notice and the profile links edit nothing either, and follow every rule below that the call bar does. Neither is pinned: both sit in the flow of the document at the end of the page, so nothing is covered and no space is reserved.
  • The call bar edits nothing. It adds one element of its own at wp_footer, with no JavaScript at all and with every style rule namespaced under .marcelo-call-bar, so it cannot restyle a single element the site already had. It reserves its own height as padding on the body rather than sitting permanently on top of the page’s last line, and it hides itself when the page is printed. The phone number is checked against a strict pattern before it is stored and escaped again on the way out.

Do I need a Marcelo account?

To use it as intended, yes — the plugin is the site-side half of connecting a website to https://meetmarcelo.ai. The plugin itself is free and GPL, works on its own, and sends nothing anywhere.

External services

This plugin can place Google tags built from identifiers stored in its own settings — a Google Analytics measurement id, a Google Tag Manager container id, a Google Ads conversion id. Wherever one of those is stored, the plugin enqueues Google’s own tag script for it, and that script is fetched by the visitor’s own browser, directly from Google, every time a page loads:

  • https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX — Google Analytics, where a measurement id is stored.
  • https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXX — Google Tag Manager, where a container id is stored.
  • https://www.googletagmanager.com/gtag/js?id=AW-XXXXXXXXX — Google Ads, where a conversion id is stored.

This is the ordinary way any site places these tags, by hand or through any other plugin — the plugin itself never contacts Google or sends it anything; it only writes the <script src> that causes the visitor’s browser to. A stored Search Console verification token loads nothing at all: it is only ever printed as a <meta> tag.

This service is provided by Google. Terms of service: https://policies.google.com/terms. Privacy policy: https://policies.google.com/privacy.

Gratuitosui piani a pagamento
Testato fino alla versione
WordPress 7.0.4
Questo plugin ora può essere scaricato per il tuo sito .