diff --git a/documentation/audits/seo-2026-10-10/not-indexed.md b/documentation/audits/seo-2026-10-10/not-indexed.md new file mode 100644 index 00000000..e330dabc --- /dev/null +++ b/documentation/audits/seo-2026-10-10/not-indexed.md @@ -0,0 +1,130 @@ +# Search Console — the seven not-indexed URLs, with a verdict each (2026-10-10) + +> **Read in the operator's own Chrome** (Claude in Chrome, property `sc-domain:felhom.eu`), by opening +> each of the five „not indexed" reasons and copying its URL list. Property language is Hungarian, so +> the reason names are quoted as Search Console shows them. +> +> **State at the time of reading:** 6 indexed, **7 not indexed**, five reasons. Last index update +> 2026-10-04. + +--- + +## The table + +| # | URL | Search Console's reason | Verdict | Why | +|---|---|---|---|---| +| 1 | `https://www.felhom.eu/` | Alternatív oldal megfelelő kanonikus címkével | **EXPECTED** | The `www.` host serves the same page and its `canonical` points at `https://felhom.eu/`. Exactly one of the pair should be indexed, and the right one is. Nothing to fix. | +| 2 | `https://www.felhom.eu/kapcsolat` | Alternatív oldal megfelelő kanonikus címkével | **EXPECTED** | Same as #1, for the contact page. | +| 3 | `https://www.felhom.eu/api/contact` | Nem található (404) | **OUR SIDE — FIXED** | This is the contact form's **POST endpoint**, not a page; a GET returns 404. Google reached it anyway (first crawled 2026-04-29) and reports a 404 on the site. Fixed by adding `Disallow: /api/` to `website/robots.txt` in this session, so it is not crawled as a page again. The endpoint itself is unchanged and the form still works. | +| 4 | `http://felhom.eu/` | Átirányítást tartalmazó oldal | **EXPECTED** | The plain-HTTP home page redirects to HTTPS. The redirect is the point; the HTTPS page is indexed. Nothing to fix. | +| 5 | `https://felhom.eu/letoltes` | Felfedezve – jelenleg nincs indexelve | **NOT A FAULT — Google's queue** | Google knows the URL and **has not crawled it yet** („Utolsó feltérképezés: nincs"). The page is reachable, is in the sitemap, is linked from the nav and carries its own title, description and canonical. This is the crawl budget of a new, low-authority site, not a defect. The lever is the operator's „Indexelés kérése". | +| 6 | `https://felhom.eu/en/download` | Felfedezve – jelenleg nincs indexelve | **NOT A FAULT — Google's queue** | Same as #5, for the English twin. | +| 7 | `https://felhom.eu/sitemap.xml` | Feltérképezve – jelenleg nincs indexelve | **EXPECTED** | A sitemap is not a page and is never meant to appear in results. Google crawled it (2026-09-17) and correctly did not index it. Nothing to fix. | + +**Totals:** 4 expected by design, 2 waiting on Google, **1 fault on our side, fixed in this session**. + +--- + +## What was fixed here + +**`website/robots.txt`** gained, with its reason in a comment: + +``` +Disallow: /api/ +``` + +Nothing else on the site was changed for indexing. The canonical tags, the `hreflang` pairs, the +per-page titles and the sitemap were already correct and were deliberately **not** redone. + +--- + +## The sitemap entry is stale — this needs the operator + +Read on the same day from Search Console → Indexelés → **Webhelytérképek**: + +| Submitted sitemap | Type | Submitted | Last read | State | Pages discovered | +|---|---|---|---|---|---| +| `https://felhom.eu/sitemap.xml?v=2` | Webhelytérkép | 2026-02-11 | 2026-10-05 | Sikeres | **8** | + +Two things are wrong with that row, and **neither can be fixed from the website**: + +1. **The submitted URL carries `?v=2`.** `robots.txt` advertises the clean + `https://felhom.eu/sitemap.xml`, so the submitted entry and the advertised one are different URLs. +2. **It reports 8 discovered pages while the sitemap holds 18.** The file listed 16 after the English + twins landed on 2026-10-08 and 18 after this session added `/teszteles` and `/en/testing`. The + number 8 is what Google took from an older read; the last read (2026-10-05) predates both changes. + +--- + +## The exact clicks for the operator + +All of this is in Search Console, property **felhom.eu**. CC does not submit anything here; these are +the operator's own clicks. + +**A. Remove the old sitemap entry** +1. Left menu → **Indexelés → Webhelytérképek**. +2. In „Beküldött webhelytérképek", click the row `https://felhom.eu/sitemap.xml?v=2`. +3. Top right of the detail panel → the three-dot menu → **„Webhelytérkép eltávolítása"**. + +**B. Submit the clean sitemap** +1. Same page, the „Új webhelytérkép hozzáadása" box at the top. +2. Type `sitemap.xml` (the `https://felhom.eu/` part is already in front of the field). +3. Click **KÜLDÉS**. The row should come back as „Sikeres" within a few minutes, and the discovered + page count should rise from 8 towards 18 over the following days. + +**C. Ask for indexing on three pages** +For each of these three URLs in turn: + +- `https://felhom.eu/` +- `https://felhom.eu/teszteles` +- `https://felhom.eu/alkalmazasok` + +1. Paste the URL into the search box at the very top („A(z) »felhom.eu« alá tartozó bármelyik URL-t + ellenőrizheti") and press Enter. +2. Wait for the check to finish (a few seconds). +3. Click **„Indexelés kérése"**, then wait for the „Indexelés kérve" confirmation before moving to the + next URL. + +Google rate-limits this, so if the third one refuses, leave it for the next day. Requesting indexing +is a **hint, not a command** — it usually takes days, and it does not guarantee indexing. + +--- + +## Performance baseline — the number to compare against in a month + +Search Console → Teljesítmény, search type Web, **last 3 months (2026-07-07 … 2026-10-06)**: + +| Metric | Value | +|---|---| +| Összes kattintás | **0** | +| Összes megjelenítés | **47** | +| Átlagos CTR | **0 %** | +| Átlagos pozíció | **73** | + +**Every query with an impression** (there are only nine, so this is the whole list, not a top-10 cut): + +| # | Query | Clicks | Impressions | CTR | Position | +|---|---|---|---|---|---| +| 1 | felhő tárhely | 0 | 18 | 0 % | 98.6 | +| 2 | felhőtárhely | 0 | 5 | 0 % | 99.0 | +| 3 | felhő alapú tárhely | 0 | 3 | 0 % | 92.0 | +| 4 | biztonsági mentés dokumentumok | 0 | 2 | 0 % | 85.0 | +| 5 | ingyenes felhő tárhelyek | 0 | 2 | 0 % | 95.5 | +| 6 | minden ok | 0 | 1 | 0 % | **2.0** | +| 7 | saját meghajtó | 0 | 1 | 0 % | 58.0 | +| 8 | saját felhő tárhely | 0 | 1 | 0 % | 83.0 | +| 9 | felhő szolgáltatás | 0 | 1 | 0 % | 100.0 | + +**What this says, plainly.** Eight of the nine queries sit at position 58–100 — that is page six and +worse, where nobody looks, which is why 47 impressions produced zero clicks. They are also the wrong +queries: „felhő tárhely" is what someone types when they want Google Drive, and against Drive, iCloud +and Dropbox this site will not rank. The one query at position 2 („minden ok") is an accident of +wording, not an intent anyone can sell to. + +**The conclusion this baseline supports:** search will not deliver the first five testers. The page +built in this session exists so that people who arrive **from a person** — a colleague, a friend, a +Facebook group — land on something that answers „what do I need, and what do I get". Search is the +slow lane and is worth keeping correct, not worth waiting for. + +**Re-read this table in a month (2026-11-10)** and compare the four headline numbers and the position +of any query that mentions „otthoni szerver" or „saját felhő", which is what the new page targets. diff --git a/marketing/CHANGELOG.md b/marketing/CHANGELOG.md index e757989e..f68bd8f0 100644 --- a/marketing/CHANGELOG.md +++ b/marketing/CHANGELOG.md @@ -1,3 +1,25 @@ +## 2026-10-10 — a three-week tester campaign (COPY.md §7), and schedule-post learns --link + +- **Five Hungarian posts** written into `facebook/COPY.md` §7, for Tuesdays and Thursdays 19:00 + Europe/Budapest over three weeks: 2026-10-13 (tester recruitment → `/teszteles`), 10-15 (where + your photos are → `/biztonsagimentes`), 10-20 (Grocy + LubeLogger → `/alkalmazasok`), 10-22 (the + recovery code → `/gyik`), 10-27 (what the box does today → `/`). **The Monday post scheduled for + 2026-10-12 19:00 (§6.2) was not touched**, and no slot falls on the same day as it. +- **Every claim carries a source comment** naming the page and line it already stands on. No price, + no availability promise, no response-time promise. 471–514 characters each. +- **Zero emoji, deliberately, though the brief allowed two:** §6's reasoning holds — the brand does + not use them and the website gate keeps them at 0, so zero is the only value consistent with the + other surfaces. Checked with a matcher that was first shown to convict a real emoji. +- **The app count says 58**, matching every prose claim on the website. The apps page renders 59 + cards and the catalog holds 60 template directories; that gap is NOT resolved here and is filed as + a register row. +- **`scripts/facebook/fb_probe.py` gained `--link`** (default unchanged: `https://felhom.eu/`). + Before this, every scheduled post attached the home page's preview card whatever its text said — + so a post about `/teszteles` would have sent the people who clicked its card to the home page, and + the card is what a reader clicks. `build_parser()` was split out of `main()` so a test can parse + argv without running a command. **Red-proved:** with the flag removed both new tests fail with + `'Namespace' object has no attribute 'link'`; with it, the suite is 32 green. + # marketing — CHANGELOG ## facebook — the Page's first post, drafted and SCHEDULED (2026-10-09) diff --git a/marketing/facebook/COPY.md b/marketing/facebook/COPY.md index 24cdad27..074a99c7 100644 --- a/marketing/facebook/COPY.md +++ b/marketing/facebook/COPY.md @@ -207,3 +207,127 @@ Minden éjjel mentés készül három helyre. A távoli mentés kulcsát egyedü Most néhány magyar háztartással zárt tesztet indítunk. Nem kötelez semmire, először csak beszélgetünk: https://felhom.eu/kapcsolat ``` + + +## 7. Háromhetes kampány — tesztelőket keresünk (2026-10-10) + +A cél **nem** az elérés, hanem **öt tesztelő háztartás**. Ezért az első poszt a konkrét ajánlat, a +többi négy pedig egy-egy okot mutat meg, amiért valaki egyáltalán akarna otthoni szervert — és +mindegyik ugyanoda vezet vissza. + +**A szabályok, amiket ez az öt poszt betart:** + +- **Minden állítás ma is ott van a weboldalon**, soronként megjelölve forrás-kommenttel. Új ígéret + nincs. Ár nincs, rendelkezésre állás nincs, válaszidő nincs. +- **Emodzsi: egy sem.** A §6 indoklása itt is áll: a Felhom arculata nem használ emodzsit, és a + weboldal gate-je 0-ra tartja. A feladat „legfeljebb 2 emodzsit" engedett — a 0 ennek a része, és + ez az egyetlen érték, ami a többi felülettel egyezik. +- **Hashtag: egy sem** (§6 indoklása). +- **Az első két sor önmagában elmondja a lényeget**, mert a Facebook kb. három sor után „Továbbiak"-ra + vág. +- **Egy link a végén.** A linket a `--link` kapcsoló is megkapja, nem csak a szöveg: a megjelenő + kártyára kattint az olvasó, és 2026-10-10 előtt minden ütemezett poszt a `https://felhom.eu/` + kártyáját vitte, bármiről is szólt. +- **Tegező hangnem, „kérjük" nélkül.** Mind magyar; angol változat nem készül (a zárt teszt magyar + háztartásoknak szól). + +**Az ütemezés** keddenként és csütörtökönként 19:00-kor (Europe/Budapest), három héten át. A hétfői, +már beütemezett poszt (2026-10-12 19:00, §6.2) **érintetlen marad**, és egyik időpont sem esik vele +egy napra. + +| # | Szakasz | Időpont (Budapest) | Nap | Link (`--link`) | +|---|---|---|---|---| +| 1 | 7.1 | 2026-10-13 19:00 | kedd | `https://felhom.eu/teszteles` | +| 2 | 7.2 | 2026-10-15 19:00 | csütörtök | `https://felhom.eu/biztonsagimentes` | +| 3 | 7.3 | 2026-10-20 19:00 | kedd | `https://felhom.eu/alkalmazasok` | +| 4 | 7.4 | 2026-10-22 19:00 | csütörtök | `https://felhom.eu/gyik` | +| 5 | 7.5 | 2026-10-27 19:00 | kedd | `https://felhom.eu/` | + +### 7.1 + + + + + + + + +``` +Keresünk öt magyar háztartást, aki kipróbálja az otthoni szerverünket. + +A teszt alatt nincs díj — se tőled, se felénk. A szervert mi állítjuk be nálad és mi üzemeltetjük, a domaint pedig két évre mi fizetjük, és az a te nevedre szól: ha a teszt véget ér, nálad marad. + +Cserébe egyetlen dolgot kérünk: mondd el, mi nem jó benne. + +Informatikai tudás nem kell — egy gép kell, ami bekapcsolva tud maradni, és egy kis türelem. + +Nem kötelez semmire: https://felhom.eu/teszteles +``` + +### 7.2 + + + + + +``` +Hol vannak most a fotóid? + +Ha a válasz „valahol a felhőben", akkor három kérdés jön utána: meddig ingyenes, ki fér hozzá, és mi történik, ha egyszer kizár a fiókodból. + +A Felhom dobozon a fényképeid nálad vannak, a saját gépeden. És nem egy példányban: minden éjjel készül egy mentés a dobozon, egy másodpéldány egy második meghajtóra, és egy titkosított másolat egy távoli tárhelyre. + +Ha elmegy a net, otthon akkor is ott vannak. + +Így működik: https://felhom.eu/biztonsagimentes +``` + +### 7.3 + + + + + +``` +Egy app, amire nem gondoltál otthoni szerver kapcsán: a bevásárlólista. + +A Grocy nyilvántartja, mi van otthon, és szól, ha valami elfogyott vagy lejár. A hiányzót magától felveszi a listára, a vonalkódot a telefonod kamerájával olvasod be. + +A másik kedvencünk a LubeLogger: a családi autó története egy helyen — szervizek, tankolások, költségek, emlékeztetővel a műszakira. + +Egyik sem küld semmit senkinek: a saját gépeden futnak. Összesen 58 alkalmazás telepíthető. + +A teljes lista: https://felhom.eu/alkalmazasok +``` + +### 7.4 + + + + +``` +Van egy kód, amit nálunk sem lehet megtalálni. + +A távoli mentésed titkosítva készül, és a kulcsát egy helyreállítási kód zárja. Ez pontosan egyszer jelenik meg: a te képernyődön. Nálunk nem marad belőle másolat. + +Az egyik oldala, hogy a mentésedet rajtad kívül senki nem tudja elolvasni — mi sem. A másik, hogy ha a kód elvész, nekünk sem nyitható ki. + +Ezért kerül papírra, jó helyre. Ez az ára annak, hogy tényleg a tiéd legyen. + +Erről és a többi gyakori kérdésről: https://felhom.eu/gyik +``` + +### 7.5 + + + + +``` +Mit tud ma egy Felhom doboz? Nem terv és nem ígéret — ezek ma működő funkciók. + +A telefonod fotói maguktól feltöltődnek rá. A beszkennelt papírjaidat felismeri és kereshetővé teszi. A mappái megjelennek a Windows Intézőben és a Mac Finderben. 58 alkalmazás telepíthető rá pár kattintással, parancssor nélkül. Minden éjjel mentés készül három szinten. És ha elmegy a net, otthon akkor is eléred a fájljaidat. + +A telepítést és az üzemeltetést mi csináljuk. Te csak használod. + +https://felhom.eu/ +``` diff --git a/scripts/facebook/fb_probe.py b/scripts/facebook/fb_probe.py index 267a126f..dcf6442d 100644 --- a/scripts/facebook/fb_probe.py +++ b/scripts/facebook/fb_probe.py @@ -516,9 +516,9 @@ def scenario_sched_dry(g, page): return 0, res -def scenario_sched_post(g, page, message, when): +def scenario_sched_post(g, page, message, when, link=POST_LINK): pid, ptok = page["id"], page["token"] - c = g.call("P1-create", "POST", pid + "/feed", ptok, form=schedule_form(message, when)) + c = g.call("P1-create", "POST", pid + "/feed", ptok, form=schedule_form(message, when, link=link)) if not c.ok: log("P REFUSED: %s" % json.dumps(c.err, ensure_ascii=False)) return 6, {"created": False, "error": c.err} @@ -543,8 +543,8 @@ def scenario_sched_post(g, page, message, when): # ---------------------------------------------------------------- main -def main(argv=None): - global VERBOSE +def build_parser(): + """The CLI surface, separate from main() so a test can parse argv without running a command.""" ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) ap.add_argument("-v", action="store_true", help="print each call: method, path (no query), status, error") ap.add_argument("--version", default="v26.0", help="Graph API version (default v26.0)") @@ -555,9 +555,18 @@ def main(argv=None): help="COPY.md section to post, e.g. 6.1 or 6.2 (schedule-post)") ap.add_argument("--at", default=None, help="when to publish, 'YYYY-MM-DD HH:MM' in Europe/Budapest (schedule-post)") + ap.add_argument("--link", default=POST_LINK, + help="schedule-post: the URL whose preview card is attached (default %s). " + "The card is what a reader clicks, so a post about one page names that page " + "here, not just in its text." % POST_LINK) ap.add_argument("--dry", action="store_true", help="schedule-post: the throwaway link+schedule check, then delete it") - a = ap.parse_args(argv) + return ap + + +def main(argv=None): + global VERBOSE + a = build_parser().parse_args(argv) VERBOSE = a.v try: token = load_key(a.credentials) @@ -607,9 +616,9 @@ def run(cmd, g, token, a=None): except (ValueError, OSError) as e: log("REFUSED: %s" % e) return 2 - log("P section %s: %d characters, publishing at %s (epoch %d)" - % (a.section, len(message), a.at, when)) - rc, _ = scenario_sched_post(g, page, message, when) + log("P section %s: %d characters, link %s, publishing at %s (epoch %d)" + % (a.section, len(message), a.link, a.at, when)) + rc, _ = scenario_sched_post(g, page, message, when, link=a.link) log("schedule-post: done (rc=%d)" % rc) return rc rc, _ = scenario_d(g, page, 0) diff --git a/scripts/facebook/test_fb_probe.py b/scripts/facebook/test_fb_probe.py index df6ddc11..8075197c 100644 --- a/scripts/facebook/test_fb_probe.py +++ b/scripts/facebook/test_fb_probe.py @@ -107,6 +107,23 @@ class ScheduleForm(unittest.TestCase): f = fb_probe.schedule_form("x", fb_probe.time.time() + 3600, link=None) self.assertNotIn("link", f) + def test_a_per_post_link_reaches_the_form(self): + """2026-10-10: the campaign posts each point at their OWN page, and the preview CARD is what + a reader clicks. Before --link existed, every scheduled post attached https://felhom.eu/ no + matter what its text said, so a post about /teszteles sent its readers to the home page. + This pins the whole path: the CLI flag must reach the form.""" + a = fb_probe.build_parser().parse_args( + ["schedule-post", "--section", "7.1", "--at", "2026-10-13 19:00", + "--link", "https://felhom.eu/teszteles"]) + self.assertEqual(a.link, "https://felhom.eu/teszteles") + f = fb_probe.schedule_form("x", fb_probe.time.time() + 3600, link=a.link) + self.assertEqual(f["link"], "https://felhom.eu/teszteles") + self.assertEqual(f["published"], "false") # still unreachable, even with a link set + + def test_link_defaults_to_the_home_page_when_the_flag_is_absent(self): + a = fb_probe.build_parser().parse_args(["schedule-post", "--at", "2026-10-13 19:00"]) + self.assertEqual(a.link, "https://felhom.eu/") + class ScheduleWindow(unittest.TestCase): NOW = 1_760_000_000 diff --git a/website/robots.txt b/website/robots.txt index 1128949b..b0e0a8dc 100644 --- a/website/robots.txt +++ b/website/robots.txt @@ -1,5 +1,8 @@ User-agent: * Allow: / Disallow: /szolgaltatasok-nonpublic +# /api/ is the contact form's POST endpoint, not a page: a GET returns 404 and Search +# Console reported it as "Not found (404)" (seen 2026-10-10, first crawled 2026-04-29). +Disallow: /api/ Sitemap: https://felhom.eu/sitemap.xml \ No newline at end of file