AffClix. * * @return array{api_host:string,domain_id:string,api_key:string,api_secret:string,enabled:bool,allow_rest:bool,load_sdk:bool} */ public static function credentials() { $saved = get_option(self::OPTION_CREDENTIALS, []); return wp_parse_args( is_array($saved) ? $saved : [], [ 'api_host' => 'api.affclix.com', 'domain_id' => '', 'api_key' => '', 'api_secret' => '', 'enabled' => false, 'allow_rest' => false, 'load_sdk' => false, ] ); } /** * Persist credentials. * * @param array $values Raw values from the settings form. */ public static function save_credentials(array $values) { update_option(self::OPTION_CREDENTIALS, $values, false); } /** * The last manifest returned by POST /v1/a/distribution/connect. * * @return array */ public static function manifest() { $manifest = get_option(self::OPTION_MANIFEST, []); return is_array($manifest) ? $manifest : []; } /** * Store a manifest. * * autoload is left on: every storefront page load reads the tracking host * out of this to render the snippet, so paying for a second query per * request to avoid one autoloaded row is the wrong trade. * * @param array $manifest Manifest from the server. */ public static function save_manifest(array $manifest) { update_option(self::OPTION_MANIFEST, $manifest, true); } /** * Forget the manifest — used on disconnect. */ public static function clear_manifest() { delete_option(self::OPTION_MANIFEST); } /** * Whether the plugin has everything it needs to do anything at all. * * @return bool */ public static function is_connected() { $manifest = self::manifest(); $creds = self::credentials(); return ! empty($creds['enabled']) && ! empty($manifest['tracking_host']); } /** * A manifest value, or a default. * * @param string $key Dot-free top-level key. * @param mixed $default Returned when absent. * @return mixed */ public static function get($key, $default = null) { $manifest = self::manifest(); return isset($manifest[$key]) ? $manifest[$key] : $default; } /** * Attribution settings, falling back to the platform defaults. * * The fallback exists only for the window between activation and the first * successful handshake; once connected these always come from the server. * * @return array{cookie_name:string,window_days:int,model:string,cookie_domain:?string} */ public static function attribution() { $attr = self::get('attribution', []); return wp_parse_args( is_array($attr) ? $attr : [], [ 'cookie_name' => 'ps_attr', 'window_days' => 30, 'model' => 'last_click', 'cookie_domain' => null, ] ); } /** * The flat order-meta keys the AffClix webhook parser reads. * * Served by the handshake so the plugin and * BaseEcommerceAdapter::extractAffiliateIds() cannot drift apart. * * @return array */ public static function meta_keys() { $keys = self::get('order_meta_keys', []); return wp_parse_args( is_array($keys) ? $keys : [], [ 'campaign_id' => 'campaign_id', 'affiliate_id' => 'affiliate_id', 'click_id' => 'click_id', 'sub1' => 'sub1', 'sub2' => 'sub2', 'click_ts' => 'click_ts', 'utm_source' => 'utm_source', 'utm_medium' => 'utm_medium', 'utm_campaign' => 'utm_campaign', 'utm_content' => 'utm_content', ] ); } }