Fjern passordbeskyttede innlegg fra WordPress-loopen

WordPress lar deg passordbeskytte enkeltinnlegg, men selv med passord på plass dukker innleggene fortsatt opp i listene på forsiden, i kategoriarkivene og i RSS-feeden. For lesere uten passord blir dette bare en tittel med «Protected:» foran som de ikke kommer videre fra – og de skyver samtidig de åpne innleggene nedover. Heldigvis finnes det flere trygge måter å holde passordbeskyttede innlegg utenfor WordPress-loopen på, fra en enkel kodesnutt i functions.php til den innebygde has_password-parameteren. Denne guiden går gjennom metodene steg for steg, forklarer fordeler og ulemper, og viser de vanligste feilene underveis.

Viktige punkter

  • Problemet: Passordbeskyttede innlegg vises fortsatt i lister, arkiver og feeder, selv om innholdet er skjult.
  • Årsaken: Et passord skjuler bare innholdet – innlegget er fremdeles publisert og teller med i WordPress-loopen.
  • Enkel løsning: Filteret posts_where i functions.php fjerner innleggene fra alle frontend-lister.
  • Anbefalt løsning i dag: Parameteren has_password (fra WordPress 3.9) via pre_get_posts – tryggere og bevarer pagineringen.
  • Husk: Ta backup, bruk barnetema, og behold is_admin()-sjekken så innleggene fortsatt vises i dashbordet.
  • Grense: Passordbeskyttelse er organisering og personvern, ikke full sikkerhet – tilpassede felter og REST-API kan lekke innhold.

Hva er WordPress-loopen – kort forklart

WordPress-loopen («the loop») er koden som henter og viser innleggene dine på en side. Hver gang du ser en liste med innlegg – på forsiden, i et kategoriarkiv, i søkeresultater eller i en «siste innlegg»-widget – er det loopen som kjører. Under panseret bygger WordPress en databaseforespørsel gjennom klassen WP_Query, henter innleggene som passer, og går gjennom dem ett for ett.

Poenget er viktig for denne guiden: et passordbeskyttet innlegg er fremdeles et helt vanlig, publisert innlegg i databasen. Passordet skjuler bare innholdet i selve innlegget – ikke tittelen, og ikke det faktum at innlegget eksisterer. Derfor blir det med i loopen akkurat som alle andre publiserte innlegg, helt til du aktivt forteller forespørselen at den skal hoppe over dem.

Hvorfor vises passordbeskyttede innlegg fortsatt i loopen?

Passordbeskyttelse i WordPress er laget for å skjule innhold, ikke for å skjule at innlegget finnes. Når du legger et passord på et innlegg, skriver WordPress passordet inn i feltet post_password i databasen og setter innleggets status til publisert. For besøkende betyr det:

  • Tittelen vises i alle lister, som regel med teksten «Protected:» eller «Beskyttet:» foran.
  • I stedet for innhold vises et lite skjema der leseren kan taste inn passordet.
  • Innlegget teller med i paginering, arkiver, RSS-feeder og de fleste «relaterte innlegg»-moduler.

Dette er fornuftig standardoppførsel for de fleste nettsteder, men upraktisk hvis du blander en privat dagbok med en offentlig blogg. Da ønsker mange at de private innleggene skal være helt usynlige for andre enn dem selv, og at bare de åpne innleggene fyller forsiden. Løsningen er å endre selve forespørselen slik at innlegg med passord filtreres bort. Har du ennå ikke satt opp beskyttelsen, kan du først lese guiden vår om hvordan du passordbeskytter WordPress-bloggen din.

Før du begynner: ta backup og bruk et barnetema

Alle metodene under innebærer at du legger kode i temafilen functions.php eller i en liten egen plugin. En skrivefeil i functions.php kan gi en hvit skjerm («white screen of death») og låse deg ute av nettstedet, så forbered deg før du redigerer.

  • Ta en full sikkerhetskopi. Se vår guide om hvordan du tar backup av WordPress før du rører en eneste kodelinje.
  • Bruk et barnetema (child theme). Legger du koden i hovedtemaet, forsvinner den ved neste temaoppdatering. Et barnetema – eller en liten egendefinert plugin – gjør at endringene overlever oppdateringer.
  • Rediger trygt. Unngå den innebygde temaredigereren i WordPress-dashbordet. Bruk heller FTP eller filbehandleren hos webverten, så du raskt kan angre hvis noe går galt.

Er du komfortabel med å endre temafiler, finner du flere nyttige kodesnutter for functions.php i en egen artikkel hos oss.

Metode 1: Ekskluder innleggene med posts_where-filteret

Den klassiske metoden bruker filteret posts_where, som lar deg endre WHERE-delen av SQL-forespørselen før WordPress henter innleggene. Du legger ganske enkelt til en betingelse om at post_password skal være tomt – altså at innlegget ikke har passord. Legg denne koden i functions.php:

// Legg en betingelse i spørringen som utelater innlegg med passord
function skjul_passordbeskyttede_innlegg( $where = '' ) {
    // Gjelder bare loopene på frontend, ikke enkeltinnlegg eller admin
    if ( ! is_single() && ! is_admin() ) {
        $where .= " AND post_password = ''";
    }
    return $where;
}
add_filter( 'posts_where', 'skjul_passordbeskyttede_innlegg' );

Linje for linje: funksjonen får inn den eksisterende WHERE-teksten, og sjekken ! is_single() && ! is_admin() sørger for at filteret bare slår inn på lister og feeder på frontend – ikke når noen åpner selve innlegget (da må passordskjemaet fortsatt virke) og ikke inne i administrasjonspanelet (der du må kunne se og redigere innleggene). Filteret posts_where er fortsatt en del av WordPress-kjernen og fungerer i dagens versjoner.

Fordelen er at snutten er kort og treffer alle loopene på én gang. Ulempen er at den er ganske «bredspektret»: fordi den endrer samtlige frontend-spørringer, fjerner den også innleggene fra kategoriarkiver, tagg-arkiver og månedsarkiver. Nettopp det gjør det vanskelig å lage ett eget sted der de private innleggene likevel vises – mer om det lenger ned.

Metode 2: Bruk has_password-parameteren (anbefalt i dag)

Siden WordPress 3.9 (utgitt i 2014) finnes det en innebygd, offisielt støttet parameter for akkurat dette: has_password. Setter du den til false, returnerer WP_Query bare innlegg uten passord; setter du den til true, får du bare de passordbeskyttede. Det finnes også en søsterparameter, post_password, som matcher et bestemt passord – og hvis begge er satt, er det post_password som gjelder.

Den ryddigste måten å bruke den på er via pre_get_posts, en action som lar deg justere spørringen før den kjøres – uten å skrive rå SQL. Da unngår du også å ødelegge pagineringen:

// Skjul passordbeskyttede innlegg fra hovedspørringen på frontend
function skjul_passordinnlegg_fra_loop( $query ) {
    if ( ! is_admin() && $query->is_main_query() && ! $query->is_singular() ) {
        $query->set( 'has_password', false );
    }
}
add_action( 'pre_get_posts', 'skjul_passordinnlegg_fra_loop' );

Her sier $query->is_main_query() at vi bare rører hovedspørringen på siden, mens ! $query->is_singular() sørger for at enkeltinnlegg og enkeltsider får være i fred. Fordi vi bruker den offisielle parameteren framfor rå SQL, er koden mer robust mot framtidige endringer i WordPress – og du slipper risikoen for syntaksfeil i selve SQL-setningen.

Denne metoden er å foretrekke for de fleste. Den er lettere å lese, lettere å begrense til akkurat de spørringene du vil, og den spiller på lag med måten WordPress er ment å utvides på.

Metode 3: La administratorer og redaktører fortsatt se innleggene

På et nettsted med flere forfattere vil du kanskje skjule de passordbeskyttede innleggene for vanlige besøkende, men la innloggede redaktører se dem på frontend. Da utvider du betingelsen med en sjekk på brukerens rettigheter. Eksempelet fra WPBeginner bruker funksjonen current_user_can() sammen med rettigheten read_private_posts:

function skjul_passord_for_gjester( $where = '' ) {
    if ( ! is_single() && ! is_admin() && ! current_user_can( 'read_private_posts' ) ) {
        $where .= " AND post_password = ''";
    }
    return $where;
}
add_filter( 'posts_where', 'skjul_passord_for_gjester' );

Tillegget ! current_user_can( 'read_private_posts' ) betyr: «filtrer bare bort innleggene dersom den innloggede brukeren ikke har rett til å se private innlegg». Administratorer og redaktører ser dermed fortsatt alt, mens vanlige lesere bare får de åpne innleggene. Dette er nyttig på redaksjonelle nettsteder der flere skal kunne jobbe med utkast og beskyttet innhold uten å logge inn i dashbordet hele tiden.

Sammenligning av metodene

Hvilken metode som passer best, avhenger av hvor presist du vil styre og hvor komfortabel du er med kode. Tabellen under oppsummerer forskjellene:

Sammenligning av metoder

MetodeSlik virker denPasser best forUlempe
posts_where-filterLegger AND post_password = '' til SQL-spørringenRask, enkel skjuling på hele frontendTreffer alle arkiver; vanskelig å lage egen samleside; rå SQL
pre_get_posts + has_passwordSetter has_password til false på hovedspørringenDe fleste nettsteder; presis styringKrever litt mer forståelse av spørringsobjektet
Rollebasert filterLegger til current_user_can( 'read_private_posts' )Nettsteder med flere forfattere/redaktørerMer kode; må testes mot ulike roller
Egen side eller kategoriSamler de private innleggene manuelt ett stedEnkel oversikt uten å stole bare på kodeVedlikeholdes manuelt; ikke automatisk

Hvor skal de passordbeskyttede innleggene da ligge?

Når innleggene forsvinner fra loopen, trenger du som regel et eget sted der du selv – og eventuelt noen betrodde lesere – finner dem igjen. Her er de vanligste løsningene:

  • En egen side med lenker. Lag en vanlig WordPress-side og lenk manuelt til de private innleggene. Enkelt, forutsigbart og helt uavhengig av filteret.
  • Et bokmerke eller en privat oversikt. Holder du innleggene kun for deg selv, holder det ofte med en lenkeliste du selv har.
  • Et unntak i koden for én kategori. Med pre_get_posts-metoden kan du la filteret stå over nettopp det arkivet du vil bruke som samleside.

Her er en viktig forskjell mellom metodene. Det enkle posts_where-filteret i metode 1 fjerner innleggene fra alle arkivsider, så du kan ikke lage en egen kategori som viser dem. Det var også den opprinnelige bakdelen med denne teknikken. Med pre_get_posts kan du derimot legge inn et unntak, for eksempel: if ( ! $query->is_category( 'privat' ) ), slik at akkurat kategorien «privat» fortsatt viser de beskyttede innleggene, mens de er borte overalt ellers.

Vanlige feil og fallgruver

De fleste problemene med denne teknikken skyldes ikke selve filteret, men detaljer rundt det. Her er feilene som går oftest igjen:

Du glemmer is_admin-sjekken

Dropper du ! is_admin(), forsvinner de passordbeskyttede innleggene også fra innleggsoversikten i dashbordet. Da tror mange at innleggene er slettet, mens de egentlig bare er filtrert bort fra visningen. Ta alltid med admin-sjekken.

Du bruker et globalt filter og knekker pagineringen

Et bredt posts_where-filter kan rote til sidetallene, fordi antallet innlegg per side regnes ut på en spørring som plutselig returnerer færre rader. pre_get_posts med has_password håndterer dette langt bedre.

Innleggene lekker ut i «relaterte innlegg» og widgets

Mange «relaterte innlegg»-plugins og egendefinerte widgets bygger sine egne spørringer som ikke berøres av filteret ditt. Da kan et beskyttet innlegg dukke opp likevel. Sjekk forsiden, enkeltinnlegg og eventuelle widgets etter at du har lagt inn koden.

Tittelen avslører fortsatt innlegget

Selv når du har skjult selve innleggene, vil WordPress andre steder vise tittelen med prefikset «Protected:» (standard siden versjon 2.8). Vil du endre eller fjerne prefikset, kan du bruke filteret protected_title_format:

add_filter( 'protected_title_format', function( $format ) {
    return '%s'; // fjerner «Protected:»-teksten
} );

Du redigerer hovedtemaet uten backup

Legger du koden rett i hovedtemaets functions.php, mister du den ved neste oppdatering – og en skrivefeil kan låse deg ute. Bruk barnetema eller en egen plugin, og ha alltid en fersk sikkerhetskopi. Skal du uansett gjøre større endringer, som å erstatte ord i alle innleggene dine, lønner det seg å ta backup først.

Sikkerhet og personvern: hva passordbeskyttelse faktisk gjør

Passordbeskyttelse i WordPress er et personvern- og organiseringsverktøy, ikke en fullverdig sikkerhetsmekanisme. Det er viktig å forstå grensene før du legger noe virkelig sensitivt bak et innleggspassord:

  • Passordet er delt, ikke personlig. Alle som har passordet, kommer inn – det er ikke knyttet til hver enkelt bruker.
  • Tilpassede felter er ikke beskyttet. Data du lagrer i tilpassede felter (custom fields) skjules ikke av passordet, og kan lekke ut via temaet eller API-et.
  • REST-API-et kan eksponere innhold. WordPress’ innebygde REST-API kan i enkelte oppsett avsløre mer enn du tror om beskyttede innlegg, så skjul-fra-loop-trikset gjør dem ikke usynlige overalt.
  • Vil du ha reell beskyttelse, bør innholdet ligge privat (status «privat», synlig bare for innloggede med rett rolle) eller på en helt annen, tilgangsstyrt plattform.

Kort sagt: bruk teknikken til å rydde forsiden og skåne leserne for innhold de ikke kan åpne – ikke som eneste vern om data som virkelig må holdes hemmelig.

Hvem passer dette for?

Metodene i denne guiden er mest nyttige for bloggere som blander personlig og offentlig innhold, for familier og grupper som deler private innlegg bak ett felles passord, og for redaksjonelle nettsteder som vil skille mellom det publikum ser og det forfatterne jobber med. Trenger du bare å skjule ett eller to innlegg midlertidig, kan den enkle posts_where-snutten holde. Har du et større nettsted med paginering, flere forfattere og «relaterte innlegg»-moduler, bør du velge pre_get_posts-metoden med has_password og teste grundig etterpå.

Vanlige spørsmål (FAQ)

Blir innleggene slettet når jeg fjerner dem fra loopen?

Nei. Innleggene ligger trygt i databasen med status «publisert» og alt innholdet intakt. Du endrer bare hvilke innlegg som vises i listene på frontend. Fjerner du koden igjen, dukker de opp som før.

Kan jeg fortsatt dele direktelenker til et passordbeskyttet innlegg?

Ja. Koden filtrerer bare lister og arkiver, ikke selve innleggssiden. Har noen den direkte URL-en og passordet, kommer de inn som normalt – derfor inneholder alle eksemplene en is_single()– eller is_singular()-sjekk.

Hva er forskjellen på posts_where og has_password?

posts_where er et eldre, generelt filter der du selv skriver rå SQL. has_password er en innebygd WP_Query-parameter som gjør det samme på en tryggere og mer lesbar måte, og som regel via pre_get_posts. For nye oppsett anbefales has_password.

Hvorfor dukker et beskyttet innlegg fortsatt opp i «relaterte innlegg»?

Fordi mange slike moduler bygger sine egne spørringer som ikke berøres av filteret ditt. Da må du enten konfigurere pluginen til å utelate beskyttede innlegg, eller tilpasse koden slik at den også dekker den spørringen.

Trenger jeg en plugin, eller holder det med kode?

Du trenger ingen plugin – noen få linjer i et barnetema eller en liten egendefinert plugin holder. Vil du heller slippe kode, finnes det tredjeparts-plugins som styrer synlighet og tilgang, men for akkurat dette er kodesnutten både lett og presis.