{"slug":"fluentform-feed-integration","title":"fluentform-feed-integration","summary":"Builds and audits configurable third-party Fluent Forms feed integrations with IntegrationManagerController. Covers addon/global settings, per-form feed UI, field mapping, conditional execution, smart-code parsing, synchronous versus asynchronous dispatch, ff_scheduled_actions, A","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-16T14:51:51.412067Z","repo":{"url":"https://github.com/Lonsdale201/wp-agent-skills","stars":22,"forks":2,"license":"MIT","updatedAt":"2026-09-21T19:53:59Z"},"bodyHtml":"<hr>\n<h2>name: fluentform-feed-integration\ndescription: &gt;-\nBuilds and audits configurable third-party Fluent Forms feed integrations with\nIntegrationManagerController. Covers addon/global settings, per-form feed UI,\nfield mapping, conditional execution, smart-code parsing, synchronous versus\nasynchronous dispatch, ff_scheduled_actions, Action Scheduler, result logging,\ncredential handling, retries, and idempotency. Use when adding a CRM, webhook,\nmessaging, storage, or external API connector; extending\nfluentform/get_available_form_integrations; handling\nfluentform/integration_notify_*; or reviewing an integration that currently\nsends remote requests directly from fluentform/submission_inserted.\nmetadata:\nwp-skills-author: \"Soczó Kristóf\"\nwp-skills-contact: \"mailto:lonsdale201@hotmail.com\"\nwp-skills-plugin: \"fluentform\"\nwp-skills-plugin-version-tested: \"6.2.7\"\nwp-skills-wp-version-tested: \"7.0.2\"\nwp-skills-php-min: \"7.4\"\nwp-skills-last-updated: \"2026-07-20\"</h2>\n<h1>Fluent Forms feed integrations</h1>\n<p>Use the Free-core feed manager when administrators need credentials, reusable\nper-form feeds, field mapping, conditions, logs, and background delivery. Use a\nplain <code>submission_inserted</code> listener only for small, non-configurable local work.</p>\n<p>Read <a href=\"references/integration-contract.md\">integration-contract.md</a> before\nimplementing the manager class or deciding retry/idempotency behavior.</p>\n<h2>Availability contract</h2>\n<p><code>FluentForm\\App\\Http\\Controllers\\IntegrationManagerController</code>, feed metadata,\nthe notification manager, <code>ff_scheduled_actions</code>, and bundled Action Scheduler\nare Free-core surfaces in 6.2.7. Mailchimp is a Free reference implementation.\nMany shipped connectors under <code>fluentformpro/src/Integrations</code> are Pro-only, but\ntheir existence does not make a third-party integration manager require Pro.</p>\n<p>Use the current controller directly. These aliases are deprecated in 6.2.7:</p>\n<ul>\n<li><code>FluentForm\\App\\Services\\Integrations\\IntegrationManager</code></li>\n<li><code>FluentForm\\App\\Services\\Integrations\\BaseIntegration</code></li>\n</ul>\n<h2>Decision point</h2>\n<p>Use a feed manager when at least one applies:</p>\n<ul>\n<li>admins create multiple destinations or mappings per form;</li>\n<li>delivery has form conditions or smart codes;</li>\n<li>credentials need a global connection screen;</li>\n<li>delivery should run asynchronously and appear in integration logs;</li>\n<li>a failed/replayed request needs an idempotency contract.</li>\n</ul>\n<p>Use a direct hook for bounded local metadata/state changes with no settings UI.\nDo not build a feed abstraction around a single pure calculation.</p>\n<h2>Registration workflow</h2>\n<ol>\n<li>Bootstrap once on <code>fluentform/loaded</code>; require the controller class.</li>\n<li>Choose three stable identifiers:\n<ul>\n<li>integration key for addon/global UI;</li>\n<li>namespaced option key for connection settings;</li>\n<li>feed settings key stored in <code>fluentform_form_meta</code> and used in the dynamic\nnotification hook.</li>\n</ul>\n</li>\n<li>Extend <code>IntegrationManagerController</code>, call the parent constructor, set the\ndescription/logo/category, then call <code>registerAdminHooks()</code>.</li>\n<li>Implement global settings and verify credentials server-side before setting\n<code>status =&gt; true</code>.</li>\n<li>Implement integration availability, feed defaults, settings fields, and merge\nfields. Keep <code>enabled</code> and <code>conditionals</code> in the feed schema.</li>\n<li>Implement <code>notify($feed, $formData, $entry, $form)</code> as an idempotent operation.</li>\n<li>Report every terminal result through <code>fluentform/integration_action_result</code>.</li>\n<li>Test disabled, unconfigured, condition-false, sync, async, timeout, retry, and\nduplicate delivery paths.</li>\n</ol>\n<h2>Bootstrap</h2>\n<pre><code>use FluentForm\\App\\Http\\Controllers\\IntegrationManagerController;\n\nadd_action('fluentform/loaded', static function ($app): void {\n    if (!class_exists(IntegrationManagerController::class)) {\n        return;\n    }\n\n    new Acme_FluentForm_Integration($app);\n}, 20, 1);\n</code></pre>\n<p>The constructor should use stable, namespaced keys:</p>\n<pre><code>parent::__construct(\n    $app,\n    __('Acme CRM', 'acme-addon'),\n    'acme_crm',\n    '_acme_ff_crm_settings',\n    'acme_crm_feeds',\n    20\n);\n\n$this-&gt;description = __('Send selected entries to Acme CRM.', 'acme-addon');\n$this-&gt;category    = 'crm';\n$this-&gt;logo        = plugins_url('assets/acme.svg', ACME_ADDON_FILE);\n$this-&gt;registerAdminHooks();\n</code></pre>\n<p>Do not change these keys after release without migrating the global option and\nall form-meta feed rows.</p>\n<h2>Notification contract</h2>\n<pre><code>public function notify($feed, $formData, $entry, $form)\n{\n    $entryId = (int) $entry-&gt;id;\n    $values  = isset($feed['processedValues']) &amp;&amp; is_array($feed['processedValues'])\n        ? $feed['processedValues']\n        : [];\n\n    try {\n        $result = $this-&gt;client()-&gt;upsertContact([\n            'external_key' =&gt; 'ff-entry-' . $entryId,\n            'email'        =&gt; sanitize_email((string) ($values['fieldEmailAddress'] ?? '')),\n        ]);\n\n        if (empty($result['ok'])) {\n            throw new \\RuntimeException('Remote service rejected the request.');\n        }\n\n        do_action(\n            'fluentform/integration_action_result',\n            $feed,\n            'success',\n            __('Delivered to Acme CRM.', 'acme-addon')\n        );\n    } catch (\\Throwable $error) {\n        do_action(\n            'fluentform/integration_action_result',\n            $feed,\n            'failed',\n            __('Acme CRM delivery failed.', 'acme-addon')\n        );\n\n        // Log bounded, redacted diagnostics; never expose credentials or payloads.\n    }\n}\n</code></pre>\n<p><code>processedValues</code> contains the feed settings after Fluent Forms smart-code\nparsing. <code>$formData</code> is the stored response data, and <code>$entry</code> is its parsed entry\nview. Map explicit keys; do not forward the complete arrays by default.</p>\n<h2>Async and failure semantics</h2>\n<p>Feeds default to asynchronous delivery. Fluent Forms writes a row to\n<code>ff_scheduled_actions</code>, queues <code>fluentform/schedule_feed</code> through Action\nScheduler, marks the row <code>processing</code>, then dispatches\n<code>fluentform/integration_notify_{settingsKey}</code>.</p>\n<pre><code>add_filter(\n    'fluentform/notifying_async_acme_crm',\n    static fn($async, $formId) =&gt; true,\n    10,\n    2\n);\n</code></pre>\n<p>The filter suffix is the integration key, while the notify action suffix is the\nfeed settings key. Do not interchange them.</p>\n<p>Do not advertise automatic delivery guarantees that the implementation does not\nprovide. In 6.2.7 the queue increments <code>retry_count</code> and marks <code>processing</code>, but\nthe integration callback must still record a terminal result, and exception or\nprocess-death recovery needs explicit testing. Use a stable remote idempotency key\nderived from the entry/feed, bounded timeouts, and a documented retry policy.</p>\n<h2>Security and data rules</h2>\n<ul>\n<li>Store credentials only in the global option, with autoload disabled. Never copy\nAPI keys into per-form feed values, localized JavaScript, submission meta, or\nlogs. Mask secrets when returning global settings to the UI.</li>\n<li>Verify credentials with a bounded server-side request before marking the\nconnection configured. Use TLS verification and an allowlisted service origin.</li>\n<li>Sanitize global/feed settings on save. Escape labels/help HTML for its exact\nadmin rendering context.</li>\n<li>If adding custom AJAX/REST routes, implement nonce/authentication, Fluent Forms\ncapabilities, form-level authorization, and object-level ownership yourself.</li>\n<li>Never send password fields, payment tokens, file-system paths, hidden control\nkeys, IP addresses, or the entire entry unless explicitly required and lawful.</li>\n<li>Validate mapped email/URL/ID types after smart-code expansion.</li>\n<li>Treat provider error bodies as untrusted and redact before logs or UI output.</li>\n<li>Keep <code>notify()</code> idempotent; Action Scheduler/manual retry or network ambiguity\ncan deliver the same entry more than once.</li>\n</ul>\n<h2>Pro boundary</h2>\n<p>Custom feed infrastructure is Free. A connector is Pro-dependent only when it\nuses a Pro class, field, payment object, user-registration feed, post feed, or\nother Pro-only capability. Guard that exact dependency with <code>class_exists()</code> or\n<code>method_exists()</code> and provide a clear disabled state in the integration UI.</p>\n<h2>Cross-references</h2>\n<ul>\n<li>Use <code>fluentform-submission-lifecycle</code> for feed dispatch timing.</li>\n<li>Use <code>fluentform-entries-data</code> for entry fields, meta, and permissions.</li>\n</ul>\n<h2>References</h2>\n<ul>\n<li>Official Integration Manager Controller documentation: <a href=\"https://developers.fluentforms.com/api/classes/integration-manager-controller/\">https://developers.fluentforms.com/api/classes/integration-manager-controller/</a></li>\n<li>Official integration hooks: <a href=\"https://developers.fluentforms.com/hooks/actions/integration/\">https://developers.fluentforms.com/hooks/actions/integration/</a></li>\n<li>Verified Free source paths:\n<ul>\n<li><code>fluentform/app/Http/Controllers/IntegrationManagerController.php</code></li>\n<li><code>fluentform/app/Services/Integrations/FormIntegrationService.php</code></li>\n<li><code>fluentform/app/Hooks/Handlers/GlobalNotificationHandler.php</code></li>\n<li><code>fluentform/app/Services/Integrations/GlobalNotificationService.php</code></li>\n<li><code>fluentform/app/Services/WPAsync/FluentFormAsyncRequest.php</code></li>\n<li><code>fluentform/app/Services/Integrations/MailChimp/MailChimpIntegration.php</code></li>\n</ul>\n</li>\n<li>Verified Pro examples, required only for their features:\n<ul>\n<li><code>fluentformpro/src/Integrations/ActiveCampaign/Bootstrap.php</code></li>\n<li><code>fluentformpro/src/Integrations/WebHook/Bootstrap.php</code></li>\n</ul>\n</li>\n</ul>\n","files":[{"path":"agents/openai.yaml","sizeBytes":322,"isText":true},{"path":"references/integration-contract.md","sizeBytes":7537,"isText":true},{"path":"SKILL.md","sizeBytes":9092,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-16T14:55:52.584624Z","sha256":"099D7BAFA238EF3E349017DFABF1A2F759826525F58F2B97D095B6562EF642E8","sizeBytes":7359},"review":null,"source":{"repositoryUrl":"https://github.com/Lonsdale201/wp-agent-skills","path":"fluentform/fluentform-feed-integration","license":"MIT","commit":"8820ff3c301066297e696611e3bc4ebeb47d1851","subtreeSha":"7657476BC175CD7506BF767169494C90B72435372BA28275DB8CCF7F043EC7C1","lastSyncedAt":"2026-09-22T13:51:11.366991Z"},"reviewedAt":"2026-09-16T15:12:08.350823Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/fluentform/fluentform-feed-integration"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart"},{"target":"git","command":"git clone https://github.com/Lonsdale201/wp-agent-skills.git"}]}