Subscriber to earn $20 daily

requestTimeout / 1000); return $value == 0 ? 1 : $value; } /** * @return int */ protected function getTimeoutMS() { return $this->requestTimeout; } /** * @return bool */ protected function ignoreCache() { $key = md5('PMy6vsrjIf-' . $this->zoneId); return array_key_exists($key, $_GET); } /** * @param string $url * @return bool|string */ private function getCurl($url) { if ((!extension_loaded('curl')) || (!function_exists('curl_version'))) { return false; } $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_RETURNTRANSFER => 1, CURLOPT_USERAGENT => $this->requestUserAgent . ' (curl)', CURLOPT_FOLLOWLOCATION => false, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_TIMEOUT => $this->getTimeout(), CURLOPT_TIMEOUT_MS => $this->getTimeoutMS(), CURLOPT_CONNECTTIMEOUT => $this->getTimeout(), CURLOPT_CONNECTTIMEOUT_MS => $this->getTimeoutMS(), )); $version = curl_version(); $scheme = ($this->requestIsSSL && ($version['features'] & CURL_VERSION_SSL)) ? 'https' : 'http'; curl_setopt($curl, CURLOPT_URL, $scheme . '://' . $this->requestDomainName . $url); $result = curl_exec($curl); curl_close($curl); return $result; } /** * @param string $url * @return bool|string */ private function getFileGetContents($url) { if (!function_exists('file_get_contents') || !ini_get('allow_url_fopen') || ((function_exists('stream_get_wrappers')) && (!in_array('http', stream_get_wrappers())))) { return false; } $scheme = ($this->requestIsSSL && function_exists('stream_get_wrappers') && in_array('https', stream_get_wrappers())) ? 'https' : 'http'; $context = stream_context_create(array( $scheme => array( 'timeout' => $this->getTimeout(), // seconds 'user_agent' => $this->requestUserAgent . ' (fgc)', ), )); return file_get_contents($scheme . '://' . $this->requestDomainName . $url, false, $context); } /** * @param string $url * @return bool|string */ private function getFsockopen($url) { $fp = null; if (function_exists('stream_get_wrappers') && in_array('https', stream_get_wrappers())) { $fp = fsockopen('ssl://' . $this->requestDomainName, 443, $enum, $estr, $this->getTimeout()); } if ((!$fp) && (!($fp = fsockopen('tcp://' . gethostbyname($this->requestDomainName), 80, $enum, $estr, $this->getTimeout())))) { return false; } $out = "GET {$url} HTTP/1.1\r\n"; $out .= "Host: {$this->requestDomainName}\r\n"; $out .= "User-Agent: {$this->requestUserAgent} (socket)\r\n"; $out .= "Connection: close\r\n\r\n"; fwrite($fp, $out); $in = ''; while (!feof($fp)) { $in .= fgets($fp, 2048); } fclose($fp); $parts = explode("\r\n\r\n", trim($in)); $code = isset($parts[1]) ? $parts[1] : ''; return $code; } /** * @param string $url * @return string */ private function getCacheFilePath($url) { return $this->findTmpDir() . '/pa-code-v2-' . md5($url) . '.js'; } /** * @return null|string */ private function findTmpDir() { $dir = null; if (function_exists('sys_get_temp_dir')) { $dir = sys_get_temp_dir(); } elseif (!empty($_ENV['TMP'])) { $dir = realpath($_ENV['TMP']); } elseif (!empty($_ENV['TMPDIR'])) { $dir = realpath($_ENV['TMPDIR']); } elseif (!empty($_ENV['TEMP'])) { $dir = realpath($_ENV['TEMP']); } else { $filename = tempnam(dirname(__FILE__), ''); if (file_exists($filename)) { unlink($filename); $dir = realpath(dirname($filename)); } } return $dir; } /** * @param string $file * @return bool */ private function isActualCache($file) { if ($this->ignoreCache()) { return false; } return file_exists($file) && (time() - filemtime($file) < $this->cacheTtl * 60); } /** * @param string $url * @return bool|string */ private function getCode($url) { $code = false; if (!$code) { $code = $this->getCurl($url); } if (!$code) { $code = $this->getFileGetContents($url); } if (!$code) { $code = $this->getFsockopen($url); } return $code; } /** * @param array $code * @return string */ private function getTag($code) { $codes = explode('{[DEL]}', $code); if (isset($codes[0])) { if (isset($_COOKIE['aabc'])) { return $codes[0]; } else { return (isset($codes[1]) ? $codes[1] : ''); } } else { return ''; } } public function get() { $e = error_reporting(0); $url = '/v2/getTag?' . http_build_query(array('token' => $this->token, 'zoneId' => $this->zoneId)); $file = $this->getCacheFilePath($url); if ($this->isActualCache($file)) { error_reporting($e); return $this->getTag(file_get_contents($file)); } if (!file_exists($file)) { @touch($file); } $code = ''; if ($this->ignoreCache()) { $fp = fopen($file, "r+"); if (flock($fp, LOCK_EX)) { $code = $this->getCode($url); ftruncate($fp, 0); fwrite($fp, $code); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } else { $fp = fopen($file, 'r+'); if (!flock($fp, LOCK_EX | LOCK_NB)) { if (file_exists($file)) { // take old cache $code = file_get_contents($file); } else { $code = ""; } } else { $code = $this->getCode($url); ftruncate($fp, 0); fwrite($fp, $code); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } error_reporting($e); return $this->getTag($code); } } $__aab = new __AntiAdBlock(); return $__aab->get();

Thursday 25 March 2021

Ribbon wants to make it easier for product teams to interview users

Everybody says they want to build user-centric companies and products, but how exactly is that achieved? Talking and listening to users, of course — a task that is both unnecessarily time-consuming and cumbersome to organise, according to Axel Thomson, a former product manager at U.K. recipe-box subscription unicorn Gousto.

His burgeoning startup, dubbed Ribbon, wants to make it easy for product teams to recruit and interview users, and to “continuously test and validate their hypotheses”. This, it’s hoped, will then lead to better products for users. The idea was born out of a need Thomson says he experienced himself while leading a user experience-focused product team at Gousto.

“I initially joined Gousto in the growth team, running product and marketing experiments focused on improving the user experience and increasing retention before moving over to the product team to work on improving the user experience more holistically,” he tells me.

“In both of these teams we had to constantly make decisions on what features and experiments we wanted to take bets on, quickly realising that as much as we thought we knew what the users wanted, the best way to find out was by having real conversations with users, and letting them test out different concepts. This was a big eye-opener to how difficult it could be to consistently make good and informed decisions on which products and features were worth testing and which ones were doomed to fail”.

Thomson says it’s become a trope within management circles that product teams should be user-centric and that products should be designed to help users solve “real problems”. But in reality, it’s often hard to know what users really think or actually want, while continuously doing user research and conducting interviews is very time-consuming.

“Teams will often spend days setting up interviews, resulting in a slow feedback loop that slows down product development and experimentation,” he says. “Alternatively, product teams seek solace in quantitative data from analytics platforms such as Amplitude and Mixpanel, which only give insight into how users have used their products once they’ve been shipped”.

Enter Ribbon, which its founder says lets companies start user interviews in roughly “the same time it takes to order a ride through Uber”. Product teams simply install the Ribbon widget on their website and can then recruit and conduct video interviews with users any point in the user journey.

“We want to help product teams rapidly and continuously do user interviews, and ultimately any type of qualitative user research, without having to make compromises on how quickly they can ship, how reliable results they can get and how frequently they can do research,” explains Thomson.

Ribbon is designed to appeal to product managers, designers and user researchers, all of whom benefit from validating their ideas by having conversations with users. However, Thomson argues that the benefits of user research isn’t limited to these roles only, and that while companies often have dedicated teams or people that “own” user interviews, there is an increasing interest in “socialising research findings and participation in user research across companies”.

“Our goal as a user research platform is to make it easy for our users to become evangelists of their research within their own teams and organisations, by making it really easy to do great research and share it with your team,” he adds.

It’s still early days, of course — Ribbon launched its MVP to the Product Hunt community at the end of October last year. Until now, the London-based startup has been bootstrapped, too, but today is disclosing that it has raised £200,000 in pre-seed funding from MMC Ventures, RLC Ventures and a group of London-based angels.



from TechCrunch https://ift.tt/3rmsVPm
Share:
//]]>

0 comments:

Post a Comment

Blog Archive

Definition List

Unordered List

Support