setAttribute(PDO::ATTR_TIMEOUT, 10); $pdo->exec("SELECT 0"); return $pdo; } catch(Exception $exception) { try { $error = $exception; $pdo = new PDO("sqlite:$filename"); $pdo->exec("SELECT 0"); return $pdo; } catch(Exception $exception2) { $error = $exception2; } } return $pdo; } function sqlite_escape_string($sql) { $sql = str_replace("'", "''", $sql); return $sql; } function sqlite_exec($pdo, $sql, &$error) { $rowsaffected = $pdo->exec($sql); if($rowsaffected === FALSE) { $errorinfo = $pdo->errorInfo(); $error = $errorinfo[2]; } } function sqlite_query($pdo, $sql, $fetchtype = SQLITE_ASSOC, &$error = '') { $statement = $pdo->query($sql); if($statement === FALSE) { $errorinfo = $pdo->errorInfo(); $error = $errorinfo[2]; } if($fetchtype == SQLITE_NUM) $statement->setFetchMode(PDO::FETCH_NUM); else if($fetchtype == SQLITE_ASSOC) $statement->setFetchMode(PDO::FETCH_ASSOC); else if($fetchtype == SQLITE_BOTH) $statement->setFetchMode(PDO::FETCH_BOTH); return $statement; } function sqlite_fetch_array(&$statement) { $array = $statement->fetch(); return $array; } function sqlite_fetch_single($statement) { $res = $statement->fetchColumn(); return $res; } function sqlite_close($pdo) { unset($pdo); } } //======================== DETECT =============================== if($action == 'detect') { echo 'OK'; exit(); } //======================== CREATE DB ============================ if(!file_exists($SS_DATABASE_FILENAME)) { $error = ''; $dbpointer = sqlite_open($SS_DATABASE_FILENAME, 0666, $error); if($error != '') { error_log("ERR 124: $error"); return; } $error = ''; sqlite_exec($dbpointer, 'CREATE TABLE pageview ( id INTEGER PRIMARY KEY ASC, fkbefore INTEGER, fkuser INTEGER, created DATETIME, url VARCHAR(400) ); CREATE TABLE user ( id INTEGER PRIMARY KEY ASC, uid VARCHAR(200), activity DATETIME, created DATETIME, ip VARCHAR(15), sourceurl VARCHAR(400), user_agent VARCHAR(500), http_accept VARCHAR(500), language VARCHAR(5), resolution VARCHAR(15), colors VARCHAR(20), plugins TEXT, sessiondata TEXT ); CREATE INDEX user_uid ON user(uid); CREATE INDEX user_user_agent ON user(user_agent); CREATE INDEX pageview_fkuser ON pageview(fkuser); CREATE INDEX pageview_created ON pageview(created);', $error); if($error != '') { error_log("ERR 162: $error"); return; } } else { $error = ''; $dbpointer = sqlite_open($SS_DATABASE_FILENAME, 0666, $error); if($error != '') { error_log("ERR 173: $error"); return; } } //=============================== LOG ========================================= if($action == '' || $action == 'update') { //retrieve values from _SERVER and _COOKIE $uid = isset($_COOKIE['SS_uid']) ? $_COOKIE['SS_uid'] : ''; $url = sqlite_escape_string($_SERVER['REQUEST_URI']); $ip = $_SERVER['REMOTE_ADDR']; $user_agent = sqlite_escape_string($_SERVER['HTTP_USER_AGENT']); $http_accept = sqlite_escape_string($_SERVER['HTTP_ACCEPT']); $selfhost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; $sourceurl = isset($_SERVER['HTTP_REFERER']) ? sqlite_escape_string($_SERVER['HTTP_REFERER']) : ''; $matches = array(); if(preg_match_all("/\\[[A-Za-z0-9_]*\\]/i", $SS_SESSION_FIELDS, $matches) > 0) { $sessiondata = $SS_SESSION_FIELDS; $hasdata = FALSE; foreach($matches[0] as $match) { $matchkey = trim(trim($match, '['), ']'); if(isset($SS_SERVER_DATA[$matchkey]) && ''.$SS_SERVER_DATA[$matchkey] != '') { $sessiondata = str_replace($match, $SS_SERVER_DATA[$matchkey], $sessiondata); $hasdata = TRUE; } else $sessiondata = str_replace($match, '', $sessiondata); } if(!$hasdata) $sessiondata = ''; } $language = isset($_COOKIE['SS_language']) ? sqlite_escape_string($_COOKIE['SS_language']) : ''; $resolution = isset($_COOKIE['SS_resolution']) ? sqlite_escape_string($_COOKIE['SS_resolution']) : ''; $colors = isset($_COOKIE['SS_colors']) ? sqlite_escape_string($_COOKIE['SS_colors']) : ''; $plugins = isset($_COOKIE['SS_plugins']) ? sqlite_escape_string($_COOKIE['SS_plugins']) : ''; if($url != '/favicon.ico' && $url != '/robots.txt') { if(stripos($sourceurl, $selfhost) >= 5 && stripos($sourceurl, $selfhost) <= 11) $sourceurl = ''; //merge bots if(''.$uid == '') { $botdefs = array('googlebot', 'yandexbot', 'bingbot', 'baiduspider', 'yahoo', 'mj12bot'); foreach($botdefs as $botdef) { if(stripos('__'.$user_agent, $botdef) > 1) { $res = sqlite_query($dbpointer, "SELECT uid FROM user WHERE user_agent = '$user_agent'", SQLITE_NUM, $error); $uid = ''.sqlite_fetch_single($res); unset($res); break; } } } //search for user if(''.$uid == '') { $res = sqlite_query($dbpointer, "SELECT uid FROM user WHERE user_agent = '$user_agent' AND ip = '$ip' AND http_accept = '$http_accept' AND activity > date('now', 'localtime', '-10 hour')", SQLITE_NUM, $error); if($error != '') { error_log("ERR 249: $error"); return; } $uid = ''.sqlite_fetch_single($res); unset($res); } //skip doubled pageview if(strlen($user_agent) > 2 && $url == '/' && ''.$sourceurl == '' && $http_accept == '*/*') { return; } //generate new one if(''.$uid == '') { $uid = sha1($ip.'|'.$user_agent.'|'.mt_rand(0x19A100, 0x39AA3FF)); } $sessiondata = iconv("UTF-8", "Windows-1252", $sessiondata); $sourceurl = iconv("UTF-8", "Windows-1252", $sourceurl); $url = iconv("UTF-8", "Windows-1252", $url); if($action == 'update') { $sql = "UPDATE user SET ip = '$ip', language = CASE WHEN '$language' = '' THEN language ELSE '$language' END, resolution = CASE WHEN '$resolution' = '' THEN resolution ELSE '$resolution' END, colors = CASE WHEN '$colors' = '' THEN colors ELSE '$colors' END, plugins = CASE WHEN '$plugins' = '' THEN plugins ELSE '$plugins' END WHERE uid = '$uid'"; $error = ''; sqlite_exec($dbpointer, $sql, $error); if($error != '') { error_log("ERR 286: $error"); return; } } else { //check if user already exist $error = ''; $res = sqlite_query($dbpointer, "SELECT id FROM user WHERE uid = '$uid'", SQLITE_NUM, $error); $fkuser = ''.sqlite_fetch_single($res); unset($res); if($error != '') { error_log("ERR 299: $error"); return; } if($fkuser == '') { //insert new user row. $sql = "INSERT INTO user ( uid, created, activity, ip, sourceurl, user_agent, http_accept, sessiondata, language, resolution, colors, plugins ) VALUES ( '$uid', datetime('now', 'localtime'), datetime('now', 'localtime'), '$ip', '$sourceurl', '$user_agent', '$http_accept', '$sessiondata', '$language', '$resolution', '$colors', '$plugins' );"; $error = ''; sqlite_exec($dbpointer, $sql, $error); if($error != '') { error_log("ERR 339: $error"); return; } $res = sqlite_query($dbpointer, "SELECT last_insert_rowid()"); $fkuser = ''.sqlite_fetch_single($res); unset($res); } else { $sql = "UPDATE user SET ip = '$ip', sessiondata = CASE WHEN '$sessiondata' = '' THEN sessiondata ELSE '$sessiondata' END, http_accept = '$http_accept', activity = datetime('now', 'localtime'), sourceurl = CASE WHEN sourceurl <> '' AND sourceurl IS NOT NULL THEN sourceurl WHEN ('$sourceurl' = '') THEN sourceurl ELSE '$sourceurl' END WHERE id = $fkuser"; $error = ''; sqlite_exec($dbpointer, $sql, $error); if($error != '') { error_log("ERR 367: $error"); return; } } $res = sqlite_query($dbpointer, "SELECT MAX(id) FROM pageview WHERE fkuser = $fkuser"); $fkbefore = ''.sqlite_fetch_single($res); unset($res); if($fkbefore == '') $fkbefore = 'NULL'; //insert pageview log $sql = "INSERT INTO pageview ( fkuser, fkbefore, created, url ) VALUES ( $fkuser, $fkbefore, datetime('now', 'localtime'), '$url' );"; $error = ''; sqlite_exec($dbpointer, $sql, $error); if($error != '') { error_log("ERR 394: $error"); return; } } //delete pageviews of bots older than 10 minutes $botnames = array('googlebot', 'bingbot', 'mj12bot', 'netsprint', 'baiduspider', 'yandexbot', 'ahrefsbot'); foreach($botnames as $botname) { if(stripos('_'.$user_agent, $botname) > 1) { $sql = "DELETE FROM pageview WHERE uid = '$uid' AND created < datetime('now', 'localtime', '-10 minute')"; sqlite_exec($dbpointer, $sql, $error); break; } } if($action != 'update') { ?> <", ""); $dxmlgz = tempnam(":\n\\/?><", ""); $xr = xmlwriter_open_uri($dxml); xmlwriter_start_document($xr, '1.0" encoding="Windows-1252'); xmlwriter_start_element($xr, 'root'); $islog = FALSE; //users xmlwriter_start_element($xr, 'user'); $sql = "SELECT id, created, activity, ip, sourceurl, user_agent, http_accept, sessiondata, language, resolution, colors, plugins FROM user"; if($fromactivity != '') $sql .= " WHERE activity > datetime('$fromactivity')"; $error = ''; $res = sqlite_query($dbpointer, $sql, SQLITE_ASSOC, $error); if($error != '') { error_log("ERR 546: $error"); return; } while($row = sqlite_fetch_array($res)) { xmlwriter_start_element($xr, 'row'); $colindex = 0; foreach($row as $key => $val) { $islog = TRUE; xmlwriter_write_element($xr, 'c'.$colindex, $val); $colindex++; } xmlwriter_end_element($xr); } xmlwriter_end_element($xr); unset($res); //pageviews xmlwriter_start_element($xr, 'pageview'); $sql = "SELECT id, fkuser, fkbefore, created, url FROM pageview"; if($fromid != '') $sql .= " WHERE id > $fromid "; $sql .= " ORDER BY id ASC "; $error = ''; $res = sqlite_query($dbpointer, $sql, SQLITE_ASSOC, $error); if($error != '') { error_log("ERR 577: $error"); return; } while($row = sqlite_fetch_array($res)) { xmlwriter_start_element($xr, 'row'); $colindex = 0; foreach($row as $key => $val) { $islog = TRUE; xmlwriter_write_element($xr, 'c'.$colindex, $val); $colindex++; } xmlwriter_end_element($xr); } xmlwriter_end_element($xr); unset($res); // xmlwriter_end_element($xr); xmlwriter_end_document($xr); xmlwriter_flush($xr); //compress GZIP $fs = fopen($dxml, 'rb'); $gz = gzopen($dxmlgz, 'w5'); while (!feof($fs)) { $buffer = fread($fs, 1000); gzwrite($gz, $buffer); } gzclose($gz); fclose($fs); //compress if(!$islog) { header('Content-Description: File Transfer'); header('Content-Type: none'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); } else if (file_exists($dxmlgz)) { header('Content-Description: File Transfer'); header('Content-Type: application/x-gzip'); header('Content-Disposition: attachment; filename=download.xml.gz'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: '.filesize($dxmlgz)); readfile($dxmlgz); } else if (file_exists($dxml)) { header('Content-Description: File Transfer'); header('Content-Type: text/xml'); header('Content-Disposition: attachment; filename=download.xml'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: '.filesize($dxml)); readfile($dxml); } if(file_exists($dxml)) unlink($dxml); if(file_exists($dxmlgz)) unlink($dxmlgz); } sqlite_close($dbpointer); if(isset($dbpointer)) unset($dbpointer); ?> Case Studies Archives - Verdocs https://verdocs.com/category/case-studies/ Mon, 29 Dec 2025 15:22:24 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.5 https://verdocs.com/wp-content/uploads/2020/04/Verdocs_FaveIcon.png Case Studies Archives - Verdocs https://verdocs.com/category/case-studies/ 32 32 APPCOM builds a cutting-edge mobile app with embedded eSignature workflows https://verdocs.com/appcom-builds-a-cutting-edge-mobile-app-with-embedded-esignature-workflows/ Thu, 06 Feb 2025 16:56:07 +0000 https://verdocs.com/en/?p=12676 Company: Something else: something else: About APPCOM Based in Montreal, Canada, and established in 2011 by Jean-Christophe Duchaine, APPCOM is a software development studio that builds tailor-made mobile apps and applicative Web ecosystem solutions for mid-size and large North American organizations. As the tech-agnostic Canadian team of 50, it partners to address the development of […]

The post APPCOM builds a cutting-edge mobile app with embedded eSignature workflows appeared first on Verdocs.

]]>

APPCOM builds a cutting-edge mobile app with embedded eSignature workflows

Company:

Something else:

something else:

About APPCOM

Based in Montreal, Canada, and established in 2011 by Jean-Christophe Duchaine, APPCOM is a software development studio that builds tailor-made mobile apps and applicative Web ecosystem solutions for mid-size and large North American organizations. As the tech-agnostic Canadian team of 50, it partners to address the development of digital products in an agile and flexible manner that meets the objectives and growth strategies of its clients.

The Challenge: Evaluate and implement embedded eSignature solution for custom application

In 2021 and post-COVID, AppCom was tasked with embedding document workflows and execution in a custom application for a client (not to be disclosed for this case study). The client sought a fully white-labeled and native eSignature experience for simple and complex templates within the application that APPCOM was tasked to build. Customizability was a project requirement and a key component in the evaluation process.

“Our client contracted with AppCom to build an end-to-end B2B solution, where embedded eSignature capabilities of the project were a key requirement. It was clear from the onset that existing eSignature vendors in the market would not meet our client’s needs, so we started a search process to find a highly flexible and embedded solution.”

The Solution: Custom Application with Embedded Document Workflows

AppCom connected with Verdocs during the technology evaluation process and saw that Verdocs embedded solution would meet their client’s needs. Given the complex needs of their clients, having direct access to the Verdocs team to help speed up the implementation and meet their clients needs.

Jean-Christophe says, “The collaboration on the technical side was really interesting and a big plus. It was the first time we had ever talked to the dev team that was actually working on the API and back-end. Not only was it easier to collaborate, but we spoke the same language, which usually when you implement a third-party solution, you don’t really talk to a technical person.”

By working closely with Verdocs, AppCom commitment to deadlines was keep intact. AppCom was able to deliver the end solution for their client in days rather than several weeks while delivering capabilities that exceed their client’s expectations.

The post APPCOM builds a cutting-edge mobile app with embedded eSignature workflows appeared first on Verdocs.

]]>
Foundations Streamlines Operations with Verdocs https://verdocs.com/foundations-streamlines-operations-with-verdocs/ Wed, 23 Oct 2024 13:55:20 +0000 https://verdocs.com/en/?p=12545 Company: Something else: something else: About Foundations Inc. In 1992, the Schwartz Foundation created Foundations, Inc., a nonprofit community service organization, to operate afterschool enrichment programs for children and families in underserved neighborhoods. Thirty years later, Foundations has grown and diversified, building and sharing our expertise in learning throughout the day and leading a movement […]

The post Foundations Streamlines Operations with Verdocs appeared first on Verdocs.

]]>

Foundations Streamlines Operations with Verdocs

Company:

Something else:

something else:

About Foundations Inc.

In 1992, the Schwartz Foundation created Foundations, Inc., a nonprofit community service organization, to operate afterschool enrichment programs for children and families in underserved neighborhoods. Thirty years later, Foundations has grown and diversified, building and sharing our expertise in learning throughout the day and leading a movement of new thinking about educational innovation and program design.

The Challenge: Existing Operational Practices were Difficult and Outdated

As a nonprofit organization serving the educational needs of young children, Foundations manages three important parties: Parents/students, student tutors, and Foundations. Foundations, as an organization, assist the academic needs of 80-120 students by matching tutors who are paid by Foundations.

Tutors are vetted and onboarded by Foundations and paired with students, who are tutored daily throughout the year. For foundations to pay tutors and for payroll to be run, a “Tutor Log” must be completed and signed by parents, tutors, and Foundations, attesting the students were tutored for the duration of the log. A quick turnaround time is critical for all parties for payroll to be run.

There are multiple challenges in this document workflow. Both parents and tutors are not always tech-savvy, and many don’t have computers. Foundations needed flexibility to meet the abilities of both parents and tutors to have bi-weekly tutoring logs completed on time. Kate DeValerio, Director of Human Resources at Foundations, says:

“We constantly juggle many moving parts between offer letters, internal paperwork, and tutor logs. We needed a centralized solution instead of emails to track all of these moving parts in our operations while having the flexibility our parents and tutors need given the remote nature of student learning.”

The Solution: A flexible and modern eSignature solution

In the summer of 2020, Kate DeValerio began evaluating eSignature solutions in the market. She considered Docusign, PandaDoc, and Adobe Sign and Verdocs. She proceeded with Verdocs because the web platform allowed Foundations the versatility and flexibility it needed to simplify its operations.

Verdocs and Foundations worked closely to optimize the best way to reach parents via in-person links and SMS capabilities. Reusable templates allowed them to avoid rebuilding templates for existing tutors and parents. Parents and tutors were generally unsophisticated with technology, and many lacked computer access. Verdocs made it easy for Foundations to reach them on their mobile devices, enabling them to complete forms in a timely manner.

The Results: Faster Turnaround, Time Savings, Happier Parents and Tutors

With Verdocs, Foundations experienced tangible benefits:

  1. On average, the turnaround time to execute documents decreased from days to hours, saving foundations hundreds of hours to chase incomplete documents.
  2. The HR team at Foundations all had access to Verdocs, simplifying digital access to all pending and executed documents.
  3. Enabling tutors and parents to digitally execute thousands of logs increased satisfaction with their experience with Foundations.

 

Kate DeValerio says:

“Verdocs has given us the flexibility to deliver experiences that allow us to reach our clients in the ways that work best for them. The team at Verdocs has supported our growth by helping us streamline our operations with digital documents and workflows..”

The post Foundations Streamlines Operations with Verdocs appeared first on Verdocs.

]]>
MRP Realty Boosts Efficiency and Streamlines Client Experience with Verdocs Embedded Document Workflows https://verdocs.com/mrp-realty-boosts-efficiency-and-streamlines-client-experience-with-verdocs-embedded-document-workflows/ Fri, 18 Oct 2024 13:48:36 +0000 https://verdocs.com/en/?p=11842 Company: Something else: something else: About MRP Realty Based in Washington, D.C., with offices in Philadelphia and New York City, MRP Realty is a leading owner, developer, and operator of office, industrial, residential, and mixed-use real estate. Since 2005, MRP Realty has deployed nearly $3 billion in total capitalization, with another $2+ billion of active […]

The post MRP Realty Boosts Efficiency and Streamlines Client Experience with Verdocs Embedded Document Workflows appeared first on Verdocs.

]]>

MRP Realty Boosts Efficiency and Streamlines Client Experience with Verdocs Embedded Document Workflows

Company:

Something else:

something else:

About MRP Realty

Based in Washington, D.C., with offices in Philadelphia and New York City, MRP Realty is a leading owner, developer, and operator of office, industrial, residential, and mixed-use real estate. Since 2005, MRP Realty has deployed nearly $3 billion in total capitalization, with another $2+ billion of active residential, office, mixed-use, and industrial projects underway. MRP’s combined development assets total more than 16 million square feet, with an additional 8 million square feet under management. The company has been actively involved in over 20 million square feet of development and investment, with a total capitalization over $4.5 billion in the Mid-Atlantic region.

The Challenge: Existing Property Management Practices were Outdated and Inefficient

As a property owner and manager of commercial office buildings, MRP Realty faced two distinct challenges: managing new tenants and existing tenants.

Managing new tenants required executing lease documents and typical onboarding consents of their tenant’s employees. The existing tenants had various needs: visitor management, facilities reservations, and access to various facilities within the buildings, all of which require a form of document execution.

The daily challenge of managing tenants across the 20 commercial office buildings in its portfolio was staggering. Each office building had between 200-600 people, and processing all the paperwork for new and existing tenants was daunting and time-consuming. Maggie Johnson, Product and Operations at MRP Realty, says:

“Our existing document process was very manual. Everything was emailed to our clients, signed, and sent back. When not signed, we would have to send reminders. We would have to download and put the executed files into the relevant folders. We spent countless hours performing monthly audits of all consents. The status quo was very painful.”

The Solution: Custom Application with Embedded Document Workflows

MRP Realty decided to build a simple, fully branded application called Passport to manage all tenants’ needs across its portfolio. Passport leveraged Verdocs’ unique capabilities to own the entire document lifecycle within the application and provide a fully branded experience for its users.

Templates for leases, fitness center waivers, amenity space waivers, rules and regulations, and Passport waivers were created once. These templates would seamlessly populate the user’s information when a document must be executed. In-app alerts are sent to the user when documents, leases, and renewals are ready to be eSigned.

The Results: Faster Turnaround, Time Savings, Reduced Risk and Higher Client Satisfaction

With Verdocs, MRP experienced immediate benefits:

  1. On average, the turnaround time to execute documents decreased from days to hours.
  2. On an annual basis, the property management team has saved hundreds of hours in their monthly tenant audit.
  3. The property management team has saved 10 minutes per tenant on average during the onboarding process; when multiplied by thousands of tenants, the efficiencies have been enormous.
  4. Tenant and client satisfaction increased, given the simplicity and ease of executing various forms within Passport.
  5. Standardizing document execution has reduced risk within their operations as consents and waivers must be signed via Passport.

Maggie Johnson says, “Verdocs has allowed us to keep our clients in our environment instead of a disconnected and manual experience through email. By fully integrating document workflows in our application, we have dramatically improved operational efficiency while delivering a modern, branded experience across our commercial real estate portfolio.”

The post MRP Realty Boosts Efficiency and Streamlines Client Experience with Verdocs Embedded Document Workflows appeared first on Verdocs.

]]>