Fixed
Project:
Social Post Facebook
Version:
3.0.x-dev
Component:
Code
Priority:
Normal
Category:
Feature request
Assigned:
Reporter:
Created:
9 Jan 2026 at 22:07 UTC
Updated:
30 Apr 2026 at 22:07 UTC
Jump to comment: Most recent
Enable Auto-Posting to Facebook on Node publish, Delete, and Update without the need for additional modules like ECA or RULES.
Enable auto-posting to Facebook by:
- Create a checkbox in the node content type publish options for auto-posting.
- Post to Facebook when a node is published or republished.
- Delete the Facebook post when the node is deleted or unpublished.
- Update the Facebook post when the canonical URL changes.
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
aaronrus commentedThe changes enable auto-posting to Facebook on node publish, unpublish, or update, including:
• Checkbox in node content type publish options for enabling auto-posting
• Posting to Facebook when a node is published/republished
• Deleting the Facebook post when the node is deleted or unpublished
• Updating the Facebook post when the canonical URL changes
All of this works without requiring additional modules like ECA or Rules. I tested the functionality with the Facebook API on node create, publish, update, unpublish, and delete actions — everything behaved as expected.
Happy to help with any follow-up testing, bug fixes, or additional features if needed!
For reference:
https://git.drupalcode.org/project/social_post_facebook/-/merge_requests/16
Comment #4
aaronrus commentedFriendly follow-up / call for testers on MR !16 – this is a ready-for-review feature that adds native auto-posting to Facebook Pages directly from node events (publish, unpublish, update, delete) – no need for ECA, Rules, or other contrib modules!
Quick summary of what MR !16 does:
- Adds a simple checkbox in each content type's "Publish options" to enable auto-posting.
- On publish/republish Posts node title + canonical URL to your connected Facebook Page (Facebook auto-scrapes image via Open Graph tags – better results with good OG setup!).
- On unpublish/delete Deletes the corresponding Facebook post.
- On title/canonical URL change (update) Deletes old post and creates new one with updated link.
- Supports both per-user and site-wide Facebook authentication.
- Includes status messages on save + detailed logging for troubleshooting.
To test this yourself (requires the Social API fix):
1. Apply the small compatibility patch for Social API (fixes uninitialized property bug): https://www.drupal.org/files/issues/2025-01-22/social_api.patch
2. Install/apply this MR !16 from the GitLab link below.
3. Enable the checkbox on one or more content types.
4. Set up Facebook auth (per-user or site-wide – both work).
5. Publish/unpublish/update/delete a node and watch it sync to Facebook!
Has anyone had a chance to test/review this yet?
I'd love feedback on functionality or any tweaks needed.
Special shout-out to Keegan Rankin (@megakeegman) – I noticed some recent activity and would really value your thoughts.
Link to the MR:
https://git.drupalcode.org/project/social_post_facebook/-/merge_requests/16
Thanks in advance for any testing or reviews – this would be a great addition for anyone using this module expecting it to simply work without additional contrib modules like ECA or Rules.
Comment #5
megakeegman commentedThanks very much for the MR. I am really excited to be rebuilding engagement around this module and will review this as soon as I can. I'm just getting back from Holiday travel (plus some) and getting caught up on everything.
Comment #6
megakeegman commentedI may have more comments on this later, as I have not yet completely thought through the broader implications of taking advantage of state the way you are in order to be able to delete posts. Of course, it makes sense that you would delete posts that link to nodes that are no longer published. But I guess this should probably also be done in this module's plugin implementations (Action, Rules, Social Platform). As I understand, deletion will only be able to occur where
'social_post_facebook.post_id.' . $node->id()was actually set, so if by other posting mechanisms, this is not set, then those posts will not be affected, which is okay for now. But other posting mechanisms make possible the ability to have multiple posts that link to one node. I guess we could append one more id after node id. It could either be a hash or an incrementing id? Thoughts?Comment #7
megakeegman commentedI'm not sure that the usage of state is really appropriate here. According to https://api.drupal.org/api/drupal/core%21core.api.php/group/info_types/11.x state is mostly for temporary information about the state of your system, and less about additional data related to content. It might be more appropriate to use the keyvalue service (see pathauto module for an example).
While sorting out the details of how to handle deletion and update of existing posts, I wonder if we should maybe try for a simpler MR first, as I think if we remove that bit of complexity for the moment, we might be able to at least get native posting a bit quicker. But I am interested in everything you are trying to do.
Comment #8
wolcen commentedI can't say that technically state is incorrect, but it doesn't feel right to me either. I tend to agree that we could probably find a better place for the data, primarily for the use case where we are recording the ID (or IDs) of the posted entity. The underlying storage of state is still an acceptable place to keep this information (i.e. keyValue) - I feel like we should separate it from state in this case given it could end up blowing state up to a pretty sizable collection.
Maybe we can use an approach similar to the path_auto module? There, they identify various collections by the entity type id. I admit, this isn't a huge change, but just feels better to me.
Additionally, if we're not sure whether different backends might require different shaped inputs for the item (or items) to delete, we could have a collection for e.g. 'social_post..' (i.e. 'social_post.facebook.basic_page') such that each collection's serialized item(s) are the expected shape for that back end.
Comment #9
wolcen commentedAn additional point against using "state" collection specifically: https://www.drupal.org/node/3177901
Thanks for these updates btw - great feature!
Comment #10
aaronrus commentedKeegan Rankin (@megakeegman)
I've created a Merge Request in the php-facebook library adding the `deletePost()` method as suggested, moving the delete logic there instead of keeping Guzzle calls in the module.
Link to the MR:
https://gitlab.com/agaric/php/php-facebook/-/merge_requests/1
Let me know if it looks good or needs changes. I tested it locally and it works. I’ll start working on the other items you have listed.
Thanks, Aaron
Comment #11
megakeegman commentedThanks for the MR in the other library. I went ahead and merged. We built this little library after major changes to the FB API. At the time there were no functioning alternatives, and now any alternatives are just quite a bit bigger. This one has at least met basic needs, but open to considering other options, especially in the case that interest in this and related modules sees some new growth.
Comment #12
aaronrus commentedKeegan Rankin (megakeegman) and Chris Thompson (wolcen)
I pushed commit 9fcee2948bab12a6a3ac7fea77faa951e554abc4 With the following changes below. I think this address your concerns if I need to make any more changes or if you have questions please let me know. Thank you for your review and suggestions.
- Move guzzle calls to the underlying client library. See Merge request at https://gitlab.com/agaric/php/php-facebook/-/merge_requests/1
- Refactored link as array element in $post variable, like $post['link']
- Moved logic to check for Auto_Post enabled from preproccess hook to Insert, Update and Alter hooks.
- Removed site-wide fallback added Auto-Posting config options in settings for sitewide or node author's account.
- Removed usage of state when storing Facebook Post IDs by replacing with key value service collections per Entity Type and Bundle.
- Fixed Doc-Block to match hook implementation for hook_ENTITY_TYPE_presave() for node_type.
Thoughts regarding the ability to have multiple posts that link to one node.
What if we stored a nested associative array in key value storage? With the key being the node ID and the value an array of page_id and post_id? For example, post:NID => ['page_id' => [post_id, post_id, ...]] Having the page_id associated with the post_id would make retrieving the long_access_token easier with multiple accounts.
To my understanding as of now the module only supports one Facebook account and page per user. As was suggested we may want to handle storing multiple post IDs in a new issue / Merge Request. Currently I am using key value storage to store the node ID and Facebook page ID as a simple string with a entity type and bundle collection. This works for the current one account one page setup we are currently using.
Comment #13
aaronrus commentedFound and fixed a bug where the form showed 'sitewide' as the default_value but runtime defaults to author when the config "posting_behavior" was unset / NULL.
Pushed new commit 4b7d59bdd3afc542d1abe6e53bee1eff26a2abff
Comment #14
aaronrus commented@megakeegman Thank you for merging the deletePost() method into the PHP Facebook library!
When I tried updating via Composer, it wouldn't pull the changes because the tag hadn't been incremented. I had to require it as a dev dependency and pin to a specific commit from main to get it working.
It would be great to cut a new tagged release so others can update/install smoothly via Composer without workarounds.
I've now incorporated the changes you and @wolcen recommended. Please let me know if there's anything else to address before we merge.
Looking forward to your reviews!
Diff link for reference: https://git.drupalcode.org/project/social_post_facebook/-/merge_requests...
Thanks!
Aaron
Comment #15
megakeegman commentedThanks! I tagged a new release for PHP Facebook. I don't have a lot of time today, but I can make reviewing this MR a priority early next week.
Comment #16
megakeegman commentedReviewing the code, these are the biggest things that stand out to me:
1. social_post_facebook_preprocess_node
why handle creating/deleting posts during preprocess? Couldn't this be done during cron? If I understand correctly, this processing will basically happen the first time someone tries to view the node page. In most cases, I imagine that this will affect the person saving the node, but that is not necessarily true. Anyway, couldn't this mean a slower page load for a random site visitor (like the page won't load until the post succeeds or fails)?
2. social_post_facebook_node_type_presave
I haven't tested this yet, but does this hook really work? Won't take me long to test. I just really did not think that would work.
3. Coming up with a good system for tracking post id and mechanism
Currently the MR just stores: 'post:' . $node->id()
I don't mind merging this before figuring this out, so maybe more a note for myself, but I would like to come up with a system for tracking posts that supports tracking multiple posts that link to the same node. Prior notes on this in comment #6. But its worth noting that I expect postNode and deletePost may require a refactor in order to generalize this functionality a bit. If I attempt that in the near future, might I be able to find you in slack to get help with testing?
4. I don't think we need any update hooks since the code seems to handle defaults for the new settings, but mentioning them just in case I missed something
Comment #17
megakeegman commentedAs for point 2 in my comment #16, that hook does work! cool.
Comment #18
megakeegman commentedI have tested this and it does appear to be working properly, posts and all. I can confirm my concern in point 1 in comment #16. Really not the worst thing.
Comment #19
aaronrus commentedI'm working on refactoring the preprocces into a queue worker for cron and the remaining items noted in comment #16. It may be next week before I can get this done.
Comment #20
aaronrus commented@megakeegman
I’ve pushed commit c46541c206f686d48ebee3212a7fc75cf866de95 to MR!16 with the following changes:
• Removed and refactored the preprocess_node() hook into a queue worker processed via Cron.
• Added support for tracking multiple Facebook post IDs per node (stored as an array in key-value storage via FacebookPostService).
• Updated FacebookAuthManager::doPost() and doDelete() to return an array (success status, post ID, and errors) to better support multi-post tracking.
• Added a per-node 'post_to_facebook' boolean field with a checkbox on node edit forms (only visible when posting is enabled for the content type).
• Refactored entity hooks (insert, update, delete) to integrate 'post_to_facebook' boolean field.
• Removed the alias alter hook; moved logic to the update hook to avoid double-posting on alias changes.
• Added social_post_facebook.schema.yml and social_post_facebook.settings.yml (with defaults for posting behavior).
Addressing notes from previous comments:
1. “Why preprocess_node()” / “Could Cron be used?” Originally, preprocess_node() was used as a minimal delay to allow Pathauto to generate the canonical URL before posting (posting in entity_insert() used the system URL, causing Facebook scraper issues with images/redirects). While it worked, as you pointed out it risked delaying page loads for random users. Cron is indeed a better approach: it offloads processing from the user session to the background. I’ve fully refactored to Cron. Although not real-time processing drush can be used to process the queue and scheduled via crontab on the command line or Ultimate Cron for independent timing. The command to process the queue manually is “drush queue:run facebook_social_post --uri=https://www.yoursite.com” Although not required as the system Cron will process the queue without any additional modules or commands outside of core.
2. “social_post_facebook_node_type_presave()” Resolved as noted in comment #17.
3. “Coming up with a good system for tracking post id and mechanism.” Implemented multi-post tracking via array storage in key-value collection (per entity_type/bundle). FacebookAuthManager now returns structured arrays to enable this. The service still supports one account/page for now, but this lays groundwork for multi-account/page support in a future issue. (Re: Slack – I’ve never used it but I’m happy to sign up and collaborate there if preferred.)
4. “I don't think we need any update hooks.” Agreed—defaults are sufficient, but I added schema and settings files anyway for completeness and future-proofing.
Regarding comment #6 on post tracking in plugins: I haven’t updated the Action, Rules, or Social Platform plugin implementations for multi-post tracking. I tested Rules and it didn’t behave correctly (possibly related to an existing open issue). Since you indicated these can wait for now, I left them untouched.
This should address all feedback so far. The code is ready for review I have tested it locally and plan to do more testing this week. Looking forward to your thoughts and hopefully getting MR!16 merged soon!
Thanks again for the detailed feedback and guidance—it’s been very helpful.
Comment #21
aaronrus commented@MegaKeegMan
I have finished testing and I am ready for !MR16 to be merged. If you have any questions or would like me to address any issues please let me know.
Thank you for your help and time review this merge request.
Comment #22
megakeegman commentedJust reviewing the code again, here from DrupalCon Chicago. Over the weekend or next week I would like to test this MR in a few ways:
Looking forward to actually utilizing post-id-tracking
Comment #23
megakeegman commentedI tested all above items per comment 22, and ebased and merged. Marking as fixed.