Tag: WordPress

  • How to Mass Disable Comments on Old WordPress Posts (5 Proven Methods)

    How to Mass Disable Comments on Old WordPress Posts (5 Proven Methods)

    If you want to disable comments on old WordPress posts without deleting the discussion that is already there, start with WordPress’s built-in age rule. Go to Settings → Discussion, enable Automatically close comments on articles older than X days, choose the cutoff, and save. WordPress stops accepting new comments on posts older than that threshold while leaving previously approved comments visible.

    That distinction matters: disabling comments is a state change; deleting comments is content destruction. If the job is “stop new comments on our archive,” there is normally no reason to empty wp_comments, truncate tables, or erase legitimate conversation.

    The quick answer: five ways to disable comments on old WordPress posts

    SituationBest methodPlugin?Existing comments preserved?
    Automatically close discussion after posts age1. Native age ruleNoYes
    Close selected existing posts or pages2. Bulk EditNoYes
    Close large or repeatable batches with shell access3. WP-CLINoYes
    Enforce an ongoing no-comments policy4. Disable Comments pluginYesUsually
    Close everything before an exact date at database scale5. Direct SQLNoYes, if you only change post state

    The native methods come first on purpose. Adding a permanent plugin for a one-time checkbox job creates another dependency to maintain. Direct SQL sits last because it is powerful and precise, but it bypasses the normal WordPress application path. Powerful does not automatically mean better. Sometimes it just means the mistake happens faster.

    Close, hide, and delete are three different jobs

    The Scope Design Comment Shutdown Ladder keeps the operations separate:

    • Close: stop new comment submissions while approved history can remain visible. This is the default recommendation.
    • Hide: change what visitors see. The data can still exist, and hiding a form is not the same as changing whether WordPress accepts comments.
    • Delete: remove comment data. This is a separate cleanup or retention decision and deserves its own backup and approval.

    Before any large WP-CLI or database change, protect a recovery point and preview what will be affected. That is the same controlled-change discipline in our safe WordPress plugin update guide: know the scope, have a way back, make the smallest necessary change, then prove the result.

    Method 1: automatically close comments after X days

    Best for: sites that want discussion on fresh articles but want old content to close automatically.

    In Settings → Discussion → Other comment settings, enable Automatically close comments on articles older than X days. Enter the age threshold that fits your publishing model—30, 60, 90, 180, or another number—and save. WordPress’s Discussion settings documentation explicitly says the setting prevents new comments after the period while leaving previously approved comments visible.

    This is different from unchecking Allow people to post comments on new articles. That option controls the default for new content going forward. The age rule is the built-in answer when you specifically need to disable comments on old WordPress posts.

    Custom post types need a separate check

    WordPress core’s old-post closure logic defaults to the standard post post type. The core reference for _close_comments_for_old_posts() shows the default and the close_comments_for_post_types filter developers can use to extend it. Do not assume the dashboard age rule automatically covers products, events, portfolios, or every custom post type.

    That matters because features can use comments under the hood. WooCommerce product reviews are an obvious example. Inventory the content types before applying a broad rule.

    Method 2: Bulk Edit selected existing posts

    Best for: a one-time batch where you know which existing posts or pages should stop accepting comments.

    1. Go to Posts → All Posts.
    2. Use date, category, author, or search filters to narrow the list.
    3. Select the posts and choose Bulk actions → Edit.
    4. Set Comments to Do not allow.
    5. Click Update and verify representative posts on the front end.

    WordPress’s Posts screen documentation confirms that Bulk Edit can change Comments Allowed for selected posts. The same general approach is available for Pages.

    Some tutorials call 20 posts a hard Bulk Edit limit. It is not. Twenty is a common default number of rows shown in the admin list. You can display more rows and work in sensible batches. On large sites, smaller batches are often smarter because they make failures easier to isolate.

    Method 3: WP-CLI for large or repeatable batches

    Best for: developers and administrators with shell access who need a repeatable, reviewable change across many posts.

    The official wp post list command can preview IDs, dates, titles, and comment status. The official wp post update command supports --comment_status=open|closed for one or more IDs.

    Preview first:

    wp post list --post_type=post --post_status=publish --fields=ID,post_date,post_title,comment_status --format=table

    Then close a known batch:

    wp post update 123 456 789 --comment_status=closed

    For a whole publication year, wp post list can pass the WordPress year query argument:

    wp post update $(wp post list --post_type=post --post_status=publish --year=2024 --format=ids) --comment_status=closed

    Use batches on very large sites. Giant all-at-once shell commands can hit argument-length limits and are harder to inspect. Years, categories, or known ID groups create safer checkpoints.

    Method 4: a Disable Comments plugin for an ongoing policy

    Best for: organizations that do not want comments at all, or want a persistent no-comments policy on particular post types or a multisite network.

    The official WordPress.org listing for Disable Comments by WPDeveloper can disable comments across posts, pages, media, or the network and remove much of the comments-related admin interface. Its documentation also says not to use it merely for selectively disabling individual posts because WordPress already supports that.

    That matches our normal WordPress rule: do not add a permanent dependency to solve a temporary checkbox problem. If “comments are not a feature here” is truly an ongoing policy, a plugin can centralize that decision. Before activation, check whether comments power product reviews, memberships, support threads, or custom workflows.

    If you add the plugin, own it like any other production dependency: updates, monitoring, rollback, and compatibility. Our website maintenance guide explains why “installed” is not the same as “owned.”

    Method 5: direct SQL for an exact cutoff

    Best for: experienced administrators who need an exact date cutoff across a very large site and have a verified database backup plus direct database access.

    Direct SQL should change the post’s comment state, not delete the comments. If the goal is to close intake, update comment_status on the matching posts. Do not truncate wp_comments or wp_commentmeta. Those operations destroy data and solve a different problem.

    Back up first, then preview. Replace wp_ if your site uses a different table prefix and replace the sample date with the real cutoff:

    SELECT ID, post_title, post_date, comment_status
    FROM wp_posts
    WHERE post_type = 'post'
      AND post_status = 'publish'
      AND post_date < '2025-01-01 00:00:00'
    ORDER BY post_date DESC
    LIMIT 50;

    Only after the preview is correct, run the narrow state change:

    UPDATE wp_posts
    SET comment_status = 'closed'
    WHERE post_type = 'post'
      AND post_status = 'publish'
      AND post_date < '2025-01-01 00:00:00';

    If pingbacks and trackbacks also need to close, handle ping_status as a separate explicit decision. A direct database change should be as narrow as the requirement. Because SQL bypasses the normal WordPress application path, verify representative posts immediately afterward and clear the normal persistent cache if the site uses one.

    If the database workflow feels opaque, use Method 1, 2, or 3 instead. The database is a lousy place to learn by vibes.

    How to verify the shutdown

    1. Open an old post that should now be closed in a private browser window.
    2. Confirm the comment form is unavailable.
    3. Confirm approved historical comments still display when preservation was part of the plan.
    4. Open a recent post that should remain open and confirm it still accepts comments.
    5. If you changed pages or custom post types, test at least one representative item from each type.
    6. If you used SQL or changed a production plugin policy, record what changed, when, and how to reverse it.

    This is the same principle behind our Web Development & Technical Optimization framework: a change is not complete when it is typed. It is complete when the intended behavior is proven.

    Frequently asked questions

    Does disabling comments delete existing comments?

    No. Closing comments prevents new submissions; it does not inherently delete approved comments already stored on the post. WordPress’s built-in age setting explicitly leaves previously approved comments visible.

    How do I disable comments on all existing posts without a plugin?

    Use Posts → All Posts → select the target posts → Bulk actions → Edit → Comments → Do not allow. For large sites with shell access, WP-CLI can set comment_status to closed for controlled batches.

    Can I disable comments on pages too?

    Yes. Pages also have a comment permission state, and the Pages screen supports bulk editing Comments Allowed. Whether a theme displays a page comment form is a separate presentation question.

    Can I reopen comments later?

    Yes. Bulk Edit and WP-CLI can set comment status back to open, and the age rule can be disabled or changed. That reversibility is another reason to prefer a state change over deletion.

    Close the door; do not burn the guestbook

    For most sites, the right way to disable comments on old WordPress posts is a native setting followed by a quick verification. Use Bulk Edit when the set is selective, WP-CLI when the work is large or repeatable, a plugin when the policy is persistent, and SQL only when the scale and precision justify bypassing the normal application path.

    If comment cleanup is one symptom of a WordPress site nobody clearly owns—updates are ad hoc, backups are theoretical, and every change feels risky—review what real WordPress maintenance support should include. Good maintenance is intentionally uneventful: scoped, recoverable, tested, and documented.

    Sources and further reading

  • How to Display Specific ACF Fields in Elementor Using JetEngine: Complete Guide

    How to Display Specific ACF Fields in Elementor Using JetEngine: Complete Guide

    If you only need to display ACF fields in Elementor, start with Elementor’s ACF dynamic tag. You do not need JetEngine Query Builder just to print a text field, image, number, date, or other supported value. JetEngine earns its place when you need a reusable Listing, need to filter a collection of posts by ACF values, or need a repeater-specific output workflow.

    That distinction matters because the most common mistake in this setup is mixing up display logic with query logic. Showing the current post’s price field is a display problem. Showing only posts where price > 100 is a query problem. Treating those as the same job creates a lot of unnecessary clicking and a surprisingly fragile site.

    TL;DR: Choose the Layer That Owns the Job

    What you need to do Best starting point Why
    Show one supported ACF value on the current post Elementor dynamic tag Simplest path; no custom query needed
    Show ACF values inside a reusable card or directory item JetEngine Listing + Dynamic Field Reusable rendering for many items
    Show only posts matching an ACF value JetEngine Query Builder + Meta Query This is a filtering/query job
    Show an ACF Repeater JetEngine Dynamic Repeater or repeater Listing Elementor’s native ACF integration does not support repeaters
    Use complex relationship/repeater data with custom ordering Normalize the data, then query/render deliberately Keeps data, query, and presentation logic separate

    The useful rule is simple: store with ACF, show with Elementor or JetEngine, select with Query Builder only when you actually need selection logic.

    The Scope Design Store → Show → Select Test

    We use a three-layer mental model for dynamic WordPress builds because it keeps the implementation maintainable.

    A three-stage dynamic content workflow: store structured fields, display them in a designed page, and select matching records.

    1. Store: What data does ACF own?

    ACF should be the stable data layer. Give fields clear names, use the field type that matches the data, and decide what each field returns before you design the front end around it.

    A relationship field can return post objects or IDs. An image field can return an array, URL, or ID. A select field can expose a value and label. Those choices affect what Elementor or JetEngine receives.

    If the data model is fuzzy, the frontend becomes a pile of workarounds wearing a nice shirt.

    2. Show: How should this value be rendered?

    If you are showing a value from the current post, user, or another known object, this is primarily a rendering job. Elementor’s official ACF integration lets supported ACF fields feed widgets through the ACF Field dynamic tag. JetEngine’s Dynamic Field can also render metadata inside pages and Listing templates.

    The question is not “Which plugin is more powerful?” The question is “Which tool solves this particular output with the least moving parts?”

    3. Select: Which records should appear at all?

    When you need to decide which posts, users, terms, or other records belong in the result set, now you have a query problem. JetEngine Query Builder is useful here because its Posts Query supports Meta Query clauses that compare stored meta values and determine which posts are returned.

    That separation is the heart of this guide.

    How to Display ACF Fields in Elementor Without JetEngine

    For a normal text, number, image, date, select, checkbox, or other supported field, start with Elementor before adding another layer.

    Elementor’s current documentation describes the basic flow:

    1. Create or edit the ACF field group and assign it to the correct post type.
    2. Populate the field on a real post so you have something to preview.
    3. Edit the relevant Elementor Single template or page.
    4. Choose a widget/control that supports dynamic data.
    5. Click the Dynamic Tags icon.
    6. Choose ACF Field.
    7. Open the ACF Field settings and select the field key you want to display.
    8. Add a fallback if an empty field would otherwise leave an awkward hole in the layout.

    Elementor maintains an official list of supported ACF field types in its ACF integration documentation. The important exception for this article is the Repeater field: Elementor explicitly says repeater fields are not supported by its native ACF integration.

    Example: Show a product subtitle

    Suppose a custom post type has an ACF text field named product_subtitle.

    You do not need a JetEngine Posts Query to display it. Add a Heading or Text widget, bind it to ACF Field → product_subtitle, and style the widget normally.

    That is the entire job.

    If the field is blank, use Elementor’s fallback setting or make a deliberate visibility decision. Do not build a query that excludes the whole post just because one display field is empty unless that is genuinely the business rule.

    When JetEngine Dynamic Field Is the Better Display Tool

    JetEngine becomes useful for rendering when you are already building a JetEngine Listing or need its dynamic callbacks and field-output options.

    A Listing is a reusable template for one item in a collection: a property card, team member, product, event, directory record, resource, testimonial, or similar repeatable object. JetEngine can then render that Listing inside a Listing Grid.

    Inside the Listing template, JetEngine’s Dynamic Field widget can pull metadata from the current listing item. Crocoblock also documents ACF as a source in its ACF-compatible dynamic workflows.

    A practical Listing might include:

    • post title from WordPress;
    • featured image or ACF image;
    • ACF price field;
    • ACF location field;
    • ACF availability field;
    • a link to the single post.

    The Listing is the show layer. It defines how each returned record looks.

    The query is separate. You can reuse the same Listing with different queries on different pages.

    That separation is powerful because you do not have to rebuild the card design every time the filtering rule changes.

    How to Filter Posts by ACF Values With JetEngine Query Builder

    Use Query Builder when the page should show a subset of posts based on custom-field values.

    Show only product posts where the ACF field color_type equals yellow.

    That is exactly the kind of job a Meta Query is built for.

    Step 1: Confirm the stored ACF value

    Before building the query, confirm the field name and the actual saved value. The label you see in the editor is not necessarily the value stored in post meta.

    For a select field, “Yellow” might be the human-readable label while the stored value is yellow. For a relationship field, you may be dealing with IDs or serialized structures depending on configuration.

    This is where many “JetEngine is broken” problems begin. The query is often fine; it is comparing against the wrong thing.

    Step 2: Create a Posts Query

    Go to JetEngine → Query Builder and create a new query. Choose Posts Query, then set the post type and any basic constraints you genuinely need.

    Step 3: Add a Meta Query clause

    Crocoblock’s current Posts Query documentation explains the Meta Query section used to compare custom-field values.

    • Field key/name: color_type
    • Compare: Equal
    • Value: yellow

    For numeric fields, use numeric comparisons only when the stored data is actually numeric. A price stored as 99.00 behaves differently from a value stored as $99.

    For multiple conditions, decide whether the relationship is AND or OR based on the business rule, not whichever choice makes the preview look right.

    Step 4: Connect the query to the Listing Grid

    Create or choose the Listing template that controls the item design. Then add a Listing Grid in Elementor, enable Use Custom Query, and select the query you created.

    Crocoblock’s Query Builder overview documents this connection between Query Builder and the Listing Grid.

    • ACF stores color_type.
    • Query Builder decides which posts qualify.
    • The Listing decides how each qualifying post looks.
    • Elementor controls the page layout around the Listing Grid.

    That is a system you can debug six months later without wanting to throw the laptop into traffic.

    ACF Repeaters Need a Repeater-Specific Workflow

    The old version of this article treated ACF repeaters too casually. They are not just another scalar field.

    Elementor’s native ACF integration does not support repeater fields. JetEngine does provide repeater-specific tools, including its Dynamic Repeater widget and repeater-based Listing workflows.

    Crocoblock’s Dynamic Repeater documentation specifically lists ACF Repeater fields as a supported source. Its Listing Template documentation also allows ACF as a repeater source when creating a repeater-based Listing.

    Use Dynamic Repeater for straightforward repeated output

    This is a good fit when each repeater row has a predictable set of subfields and the output can be represented cleanly by the Dynamic Repeater’s item format.

    • feature/value pairs;
    • staff certifications;
    • resource links;
    • office hours;
    • simple icon/text rows.

    Use a repeater Listing for richer layouts

    A dedicated Listing is better when each repeater row needs a more complex visual structure, multiple dynamic widgets, or a layout that should remain visually editable.

    • speaker cards with image, name, title, and bio;
    • product specification cards;
    • timeline entries;
    • service packages;
    • gallery items with captions and links.

    Do not assume one field widget will “loop the repeater”

    A repeater is a collection of rows containing subfields. It needs a tool that understands that row structure. Treating the whole repeater like one text field is why output becomes serialized garbage, empty content, or a mysterious Array on the front end.

    Common Reasons ACF Fields Do Not Show in Elementor or JetEngine

    When a dynamic field comes back empty, troubleshoot from the data layer outward.

    The field group is assigned to the wrong object

    Check the ACF location rules. If the field group is assigned to product posts but your Elementor preview is a normal post, the field will not have the data you expect.

    Your preview item has no value

    Dynamic templates depend on preview context. Select a representative post with real ACF data before deciding the dynamic tag is broken.

    You selected the label instead of the stored field value

    This is especially common with select, radio, checkbox, relationship, and taxonomy-style fields. Confirm what ACF stores and what the display/query tool expects.

    The return format does not match the consumer

    Image, relationship, link, and similar ACF fields can return different structures. If a widget expects an attachment ID and the field returns an array, you can get an empty or malformed result even though the field is populated.

    You used display logic to solve a query problem

    A Dynamic Field can display availability = available. It does not automatically mean the Listing Grid will exclude availability = unavailable records. Filtering belongs in the query.

    You used query logic to solve a display problem

    The reverse is just as common. If you only want to print phone_number on the current post, a custom Posts Query is unnecessary complexity.

    The field is a repeater

    Use a repeater-aware JetEngine workflow. Elementor’s native ACF dynamic tag does not support repeaters.

    Field-Type and Query Pitfalls Worth Checking

    Checkbox and multi-select fields

    Multi-value fields may be stored in structures that make exact equality the wrong comparison. Do not blindly switch to LIKE because a forum answer said so. Inspect the stored format and use the comparison that actually matches the data model.

    Numeric fields

    If you need “greater than,” “less than,” or numeric ordering, store clean numeric values and configure the query for numeric comparison. Decorative currency symbols belong in the display layer, not in the stored value you expect to sort mathematically.

    Dates

    Choose one consistent storage convention. Display formatting and query comparison are separate concerns. A pretty date like “August 18, 2026” is for humans; queries need predictable data.

    Relationship and post-object fields

    Decide whether your architecture expects IDs or post objects and normalize that data before building custom query logic around it. Scope Design’s WordPress engineering rule here is simple: normalize once, then let the rest of the system consume a predictable shape.

    For custom PHP work, ACF’s official get_field() documentation is the authoritative reference for retrieving a field value directly.

    Performance: Do Not Optimize the Wrong Layer

    ACF values stored in WordPress post meta can be extremely useful, but complex meta_query combinations across large datasets can become expensive. “Use Query Builder” is not, by itself, a performance strategy.

    Start with the actual workload:

    • How many records are queried?
    • How many meta conditions are applied?
    • Is the page paginated?
    • Does every card render expensive nested dynamic content?
    • Are you querying fields that should really be taxonomies or another indexed data structure?
    • Are you loading hundreds of records just to hide most of them with front-end conditions?

    For a directory with 30 items, you may never notice a problem. For a catalog with tens of thousands of records and several meta filters, data architecture matters a lot more than which panel you clicked in Elementor.

    Custom functionality should earn its place. Otherwise it is expensive theater.

    Keep the Integration Maintainable

    Dynamic sites usually break at the seams between plugins, not because ACF suddenly forgot how to store text.

    1. Keep field names stable after launch.
    2. Document important field return formats.
    3. Name JetEngine queries by business purpose, not vague labels such as “Query 2.”
    4. Test empty, malformed, and unexpected field states.
    5. Test a representative post for every content type.
    6. Test query results before styling the Listing.
    7. Keep rendering logic separate from filtering logic.
    8. Test plugin updates on staging when the site depends on several dynamic-content layers.

    If you manage this stack over time, our guide to safer WordPress plugin updates explains why update testing matters when several plugins share responsibility for the same page.

    A Practical Decision Checklist

    Before adding another query, widget, shortcode, or plugin setting, ask:

    • Am I storing data, displaying data, or selecting records?
    • Is this field a single value or a repeatable/relational structure?
    • What does ACF actually return for this field?
    • Does Elementor already support the field directly?
    • If I am using JetEngine, do I need a Dynamic Field, a repeater tool, a Listing, or Query Builder?
    • Is the empty state intentional?
    • Can another developer understand the setup from the names alone?
    • Will the architecture still make sense when the content grows 10×?

    If you cannot answer those questions, adding another Meta Query probably will not rescue the architecture.

    Frequently Asked Questions

    Do I need JetEngine to display ACF fields in Elementor?

    Not necessarily. Elementor supports many ACF field types through its ACF Field dynamic tag. Use JetEngine when you need its Listing system, repeater tooling, Query Builder, callbacks, or other dynamic-content features.

    Do I need Elementor Pro for ACF dynamic fields?

    Elementor documents its ACF integration as part of its dynamic-content workflow. JetEngine also supplies its own dynamic widgets for Elementor. Your exact plugin requirement depends on which rendering path you choose, so do not install Elementor Pro solely because an old tutorial says every ACF + JetEngine setup requires it.

    How do I display a specific ACF text field in Elementor?

    Edit the appropriate Elementor template, choose a widget that supports dynamic data, select Dynamic Tags → ACF Field, then choose the desired ACF field key. Use a fallback if an empty value would damage the layout.

    How do I filter posts by an ACF field value?

    Use a query layer. In JetEngine Query Builder, create a Posts Query and add a Meta Query clause using the field key, comparison operator, and target value. Then connect that query to the Listing Grid.

    Why is my ACF field not showing in Elementor dynamic tags?

    Check the ACF location rules, preview post, field type, field value, and return format. Also confirm the field type is supported by Elementor’s native ACF integration.

    Can Elementor display ACF Repeater fields directly?

    Not through Elementor’s native ACF integration. Elementor’s documentation explicitly excludes repeater fields. JetEngine can work with ACF repeaters through Dynamic Repeater and repeater Listing workflows.

    Can JetEngine use ACF fields instead of JetEngine meta fields?

    Yes, JetEngine includes ACF-compatible display and repeater workflows. You do not have to recreate every ACF field in JetEngine simply because you are using a JetEngine Listing.

    Should I use = or LIKE for an ACF meta query?

    Use the operator that matches the way the value is actually stored and the rule you intend to test. Exact scalar values are often appropriate for equality. Serialized or multi-value structures require more care. Inspect the stored value instead of guessing.

    Can I combine multiple ACF field conditions?

    Yes. JetEngine Meta Query clauses can be combined with AND/OR logic. Use AND when every condition must be true and OR when any qualifying condition is enough.

    What is the best way to display ACF relationship fields in Elementor?

    Start by deciding what the field returns and what the output should be. For simple relationships, a Listing or dynamic field may be enough. For custom ordering or complex relationship logic, normalize the selected records to predictable IDs and feed those IDs into a dedicated query/rendering path.

    Is JetEngine Query Builder faster than Elementor by default?

    No blanket claim like that is useful. Performance depends on the underlying query, record count, meta conditions, templates, caching, and data model. Query Builder is valuable because it gives you explicit query control, not because clicking it automatically makes WordPress faster.

    Build the Smallest Dynamic System That Solves the Real Problem

    ACF, Elementor, and JetEngine work well together when each tool has a clear responsibility. ACF stores structured data. Elementor and JetEngine render it. Query Builder selects records when the page actually needs filtering logic.

    That sounds obvious. It also prevents a huge percentage of the dynamic-WordPress messes we get called in to untangle.

    If your project has crossed the line from “show this field” into relationships, repeaters, directories, custom queries, conditional output, and multiple templates that all need to stay sane, Scope Design provides custom WordPress website development built around maintainable data and rendering architecture, not digital duct tape.

    And if the site is already business-critical, our WordPress maintenance services can keep the moving parts tested, updated, and supported after launch.