Vpp Man
Vpp Man

Reputation: 2546

WordPress - Programmatically insert Elementor Widgets in a page

I have Elementor Pro installed on my WordPress website and I was writing a custom plugin that will do some stuff and programmatically creates a new Page. I was able to create the Page, but the problem is, I want to insert an Elementor Widget programmatically inside this new page.

I've contacted the Elementor Support to see if they have any inputs for me. But their reply is:

As much as I'd like to assist you with this, custom code/snippet or any guidance for this is beyond the scope of our support, given that we provide support for Elementor's existing features only.

So is there anyway I can achieve this via code, I mean insert a specific Elementor Widget to a page ?

Upvotes: 5

Views: 5880

Answers (1)

Akhilesh B Chandran
Akhilesh B Chandran

Reputation: 6608

This won't be the best solution, but I will explain how I figured out a workaround.

For me, I tried monitoring my WordPress website's database to see what all changes are happening when I create a new page with Elementor. Tables that I monitored are: wp_posts and wp_postmeta. Please note that the wp_ prefix maybe different in your case, if you had chosen a different one while installing the WordPress.

When you create a page, a new row gets inserted in the wp_posts table with the post_type value page. Note down that post_id value(for the sake of explaining, let the post_id be 123).

The metadata for this page will be stored in the wp_postmeta table, and that's where Elementor stores it's data related to each Page or Post. Using phpMyAdmin, I accessed that table and searched for records that has post_id = 123 (here 123 is the ID of the page). You can use the Search tab of phpMyAdmin(after selecting the wp_postmeta table) like this:

enter image description here

Or, could run a query like this in the SQL Tab of phpMyAdmin:

SELECT * FROM `wp_postmeta` WHERE `post_id` = 123

Now you will see all the metadata attached to our page (with ID 123).

enter image description here

In my case, I had already added one widget in Elementor, for this page (ID 123) earlier. So, as you can see in the above image, it has some metadata attached to it.

That _wp_page_template = page-fullwidth.php is there because I had selected the Full Width for my Page's Template Attribute :

enter image description here

And these two values seems to be required to make it understand that the page is created using Elementor:

_elementor_edit_mode = builder
_elementor_template_type = wp-page

So we definitely need that. Then for the Elementor version values:

_elementor_version = 2.9.14
_elementor_pro_version = 2.10.3

You can make use of the constants : ELEMENTOR_VERSION (if you have free version of Elementor plugin) and ELEMENTOR_PRO_VERSION (if you have Pro version plugin). These constants are defined already if you have the respective version (free or pro) of Elementor plugin installed.

Then comes the important part, the Widget's data and the layout related data seems to be stored in the : _elementor_data and _elementor_controls_usage metakeys.

Value of _elementor_data seems to be a JSON string. So you can make use of any online JSON parser to see what it has. The value in my case was like this:

[{"id":"2e0569b","elType":"section","settings":[],"elements":[{"id":"e2a6dbb","elType":"column","settings":{"_column_size":100,"_inline_size":null},"elements":[{"id":"441552a","elType":"widget","settings":{"tag_ids":"21"},"elements":[],"widgetType":"listings_grid_new"}],"isInner":false}],"isInner":false}]

When parsed, it would look like this:

[
  {
    "id": "2e0569b",
    "elType": "section",
    "settings": [],
    "elements": [
      {
        "id": "e2a6dbb",
        "elType": "column",
        "settings": {
          "_column_size": 100,
          "_inline_size": null
        },
        "elements": [
          {
            "id": "441552a",
            "elType": "widget",
            "settings": {
              "tag_ids": "21"
            },
            "elements": [],
            "widgetType": "listings_grid_new"
          }
        ],
        "isInner": false
      }
    ],
    "isInner": false
  }
]

Since I added that Widget to my page earlier, and set the Tag ID input box with a value of 21 (via Elementor Editor), I understood that I have to pass new value replacing that 21.

Then comes the _elementor_controls_usage metakey. And the value of it was like this:

a:3:{s:17:"listings_grid_new";a:3:{s:5:"count";i:1;s:15:"control_percent";i:1;s:8:"controls";a:1:{s:7:"content";a:1:{s:13:"section_query";a:2:{s:7:"loc_ids";i:1;s:7:"tag_ids";i:1;}}}}s:6:"column";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:1:{s:6:"layout";a:1:{s:6:"layout";a:1:{s:12:"_inline_size";i:1;}}}}s:7:"section";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:0:{}}}

It's serialized data. You can use any online tool to unserialize that data. Here's what mine looks like after unserializing:

array (
  'listings_grid_new' => 
  array (
    'count' => 1,
    'control_percent' => 1,
    'controls' => 
    array (
      'content' => 
      array (
        'section_query' => 
        array (
          'loc_ids' => 1,
          'tag_ids' => 1,
        ),
      ),
    ),
  ),
  'column' => 
  array (
    'count' => 1,
    'control_percent' => 0,
    'controls' => 
    array (
      'layout' => 
      array (
        'layout' => 
        array (
          '_inline_size' => 1,
        ),
      ),
    ),
  ),
  'section' => 
  array (
    'count' => 1,
    'control_percent' => 0,
    'controls' => 
    array (
    ),
  ),
)

And it looks like basically the layout related data. So I thought not to do any editing this value, and use it as it is.


Let's cook the final thing

For creating the page, I used the wp_insert_post() method, which returns the new page_id after insertion. And after creating the page, I used the update_post_meta() method, passing this page_id and attached the metadata.

My final code would be looking like this:

//-- set the new page arguments
$new_page_args = array(
    'post_type'     => 'page',              //-- this is of type 'page'
    'post_title'    => 'My Dynamic Page',   //-- title of the page              
    'post_status'   => 'publish'            //-- publish the page
);

//-- insert the page
$new_page_id = wp_insert_post( $new_page_args );

if( is_wp_error( $new_page_id ) )
{
    echo 'Unable to create the page!';        
    die;
}

if( defined( 'ELEMENTOR_VERSION' ) )    //-- if FREE version of Elementor plugin is installed
{
    update_post_meta( $new_page_id, '_elementor_version', ELEMENTOR_VERSION );
}

if( defined( 'ELEMENTOR_PRO_VERSION' ) )    //-- if PRO version of Elementor plugin is installed
{
    update_post_meta( $new_page_id, '_elementor_pro_version', ELEMENTOR_PRO_VERSION );
}

update_post_meta( $new_page_id, '_wp_page_template', 'page-fullwidth.php' );    //-- for using full width template

//-- for Elementor
update_post_meta( $new_page_id, '_elementor_edit_mode', 'builder' );
update_post_meta( $new_page_id, '_elementor_template_type', 'wp-page' );

//-- Elementor layout
update_post_meta( $new_page_id, '_elementor_controls_usage', 'a:3:{s:17:"listings_grid_new";a:3:{s:5:"count";i:1;s:15:"control_percent";i:1;s:8:"controls";a:1:{s:7:"content";a:1:{s:13:"section_query";a:2:{s:7:"loc_ids";i:1;s:7:"tag_ids";i:1;}}}}s:6:"column";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:1:{s:6:"layout";a:1:{s:6:"layout";a:1:{s:12:"_inline_size";i:1;}}}}s:7:"section";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:0:{}}}' );

$tag_id = '56'; //-- new value
//-- Elementor data ( I have injected the new $tag_id value in the string )
update_post_meta( $new_page_id, '_elementor_data', '[{"id":"2e0569b","elType":"section","settings":[],"elements":[{"id":"e2a6dbb","elType":"column","settings":{"_column_size":100,"_inline_size":null},"elements":[{"id":"441552a","elType":"widget","settings":{"tag_ids":"'. $tag_id .'"},"elements":[],"widgetType":"listings_grid_new"}],"isInner":false}],"isInner":false}]' );

Keep in mind, this is not the perfect solution. But I explained how I figured out a workaround to this problem.

Maybe someone else would be posting a better solution. ;)

Upvotes: 7

Related Questions