Reputation: 2546
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
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:
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
).
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 :
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